diff options
Diffstat (limited to 'testcases/kernel/syscalls/ipc')
-rw-r--r-- | testcases/kernel/syscalls/ipc/msgctl/msgctl01.c | 2 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/msgget/msgget02.c | 6 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/msgstress/msgstress03.c | 7 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/.gitignore | 2 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/Makefile | 4 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/semget01.c | 187 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/semget02.c | 221 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/semget03.c | 133 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/semget05.c | 189 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semget/semget06.c | 143 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semop/.gitignore | 2 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semop/Makefile | 5 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semop/semop04.c | 93 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/semop/semop05.c | 157 | ||||
-rw-r--r-- | testcases/kernel/syscalls/ipc/shmget/shmget02.c | 28 |
15 files changed, 461 insertions, 718 deletions
diff --git a/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c b/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c index 75adcb229..56d1505fd 100644 --- a/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c +++ b/testcases/kernel/syscalls/ipc/msgctl/msgctl01.c @@ -6,7 +6,7 @@ */ /* - * Test that IPC_STAT command succeeds and the the buffer is filled with + * Test that IPC_STAT command succeeds and the buffer is filled with * correct data. */ #include <errno.h> diff --git a/testcases/kernel/syscalls/ipc/msgget/msgget02.c b/testcases/kernel/syscalls/ipc/msgget/msgget02.c index ce59a8fb5..1885599d1 100644 --- a/testcases/kernel/syscalls/ipc/msgget/msgget02.c +++ b/testcases/kernel/syscalls/ipc/msgget/msgget02.c @@ -8,11 +8,11 @@ * * Test for EEXIST, ENOENT, EACCES errors. * - * 1) msgget(2) fails if a message queue exists for key and msgflg + * - msgget(2) fails if a message queue exists for key and msgflg * specified both IPC_CREAT and IPC_EXCL. - * 2) msgget(2) fails if no message queue exists for key and msgflg + * - msgget(2) fails if no message queue exists for key and msgflg * did not specify IPC_CREAT. - * 3) msgget(2) fails if a message queue exists for key, but the + * - msgget(2) fails if a message queue exists for key, but the * calling process does not have permission to access the queue, * and does not have the CAP_IPC_OWNER capability. * diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c index 3cb70ab18..aa37d9058 100644 --- a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c +++ b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c @@ -110,11 +110,12 @@ int main(int argc, char **argv) } free_pids = tst_get_free_pids(cleanup); - if (nprocs >= free_pids) { + /* Each forked child forks once, take it into account here. */ + if (nprocs * 2 >= free_pids) { tst_resm(TINFO, "Requested number of processes higher than limit (%d > %d), " - "setting to %d", nprocs, free_pids, free_pids); - nprocs = free_pids; + "setting to %d", nprocs * 2, free_pids, free_pids); + nprocs = free_pids / 2; } srand(getpid()); diff --git a/testcases/kernel/syscalls/ipc/semget/.gitignore b/testcases/kernel/syscalls/ipc/semget/.gitignore index ce26c93b0..4519b30d2 100644 --- a/testcases/kernel/syscalls/ipc/semget/.gitignore +++ b/testcases/kernel/syscalls/ipc/semget/.gitignore @@ -1,5 +1,3 @@ /semget01 /semget02 -/semget03 /semget05 -/semget06 diff --git a/testcases/kernel/syscalls/ipc/semget/Makefile b/testcases/kernel/syscalls/ipc/semget/Makefile index 26b9f264d..b1201281d 100644 --- a/testcases/kernel/syscalls/ipc/semget/Makefile +++ b/testcases/kernel/syscalls/ipc/semget/Makefile @@ -3,10 +3,10 @@ top_srcdir ?= ../../../../.. -LTPLIBS = ltpipc +LTPLIBS = ltpnewipc include $(top_srcdir)/include/mk/testcases.mk -LTPLDLIBS = -lltpipc +LTPLDLIBS = -lltpnewipc include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/ipc/semget/semget01.c b/testcases/kernel/syscalls/ipc/semget/semget01.c index 217163b3a..872acabd3 100644 --- a/testcases/kernel/syscalls/ipc/semget/semget01.c +++ b/testcases/kernel/syscalls/ipc/semget/semget01.c @@ -1,172 +1,65 @@ +// 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 */ -/* - * NAME - * semget01.c - * - * DESCRIPTION - * semget01 - test that semget() correclty creates a semaphore set +/*\ + * [Description] * - * ALGORITHM - * loop if that option was specified - * call semget() to create the semaphore set - * check the return code - * if failure, issue a FAIL message. - * otherwise, - * if doing functionality testing - * stat the semaphore set - * if the number of primitive semaphores is correct and - * the semaphore uid == the process uid - * then, - * issue a PASS message - * otherwise - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * semget01 [-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 - * 03/2001 - Written by Wayne Boyer - * - * RESTRICTIONS - * none + * This case checks that semget() correclty creates a semaphore set. */ -#include "ipcsem.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include "lapi/sem.h" +#include "tst_test.h" +#include "libnewipc.h" +#include "tst_safe_sysv_ipc.h" -char *TCID = "semget01"; -int TST_TOTAL = 1; +static int sem_id = -1, sem_key = -1; -int sem_id_1 = -1; - -int main(int ac, char **av) +static void check_functionality(void) { - int lc; - void check_functionality(void); - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); /* global setup */ - - /* The following loop checks looping state if -i option given */ - - for (lc = 0; TEST_LOOPING(lc); lc++) { - /* reset tst_count in case we are looping */ - tst_count = 0; - - /* - * Use TEST macro to make the call - */ - - TEST(semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)); - - if (TEST_RETURN == -1) { - tst_resm(TFAIL, "%s call failed - errno = %d : %s", - TCID, TEST_ERRNO, strerror(TEST_ERRNO)); - } else { - /* get the semaphore ID */ - sem_id_1 = TEST_RETURN; - - check_functionality(); - } - - /* - * remove the semaphore that was created and mark the ID - * as invalid. - */ - if (sem_id_1 != -1) { - rm_sema(sem_id_1); - sem_id_1 = -1; - } - } + struct semid_ds semary; + union semun un_arg; - cleanup(); + un_arg.buf = &semary; + SAFE_SEMCTL(sem_id, 0, IPC_STAT, un_arg); + TST_EXP_EQ_LI(un_arg.buf->sem_nsems, PSEMS); + TST_EXP_EQ_LI(un_arg.buf->sem_perm.cuid, geteuid()); - tst_exit(); + tst_res(TPASS, "basic semaphore values are okay"); } -/* - * check_functionality() - check the functionality of the tested system call. - */ -void check_functionality(void) +static void verify_semget(void) { - struct semid_ds semary; - union semun un_arg; /* union defined in ipcsem.h */ - - /* STAT the semaphore */ - un_arg.buf = &semary; - if (semctl(sem_id_1, 0, IPC_STAT, un_arg) == -1) { - tst_brkm(TBROK, cleanup, "Could not stat the semaphore"); + TEST(semget(sem_key, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)); + if (TST_RET == -1) { + tst_res(TFAIL | TTERRNO, "semget() failed"); return; } - if (un_arg.buf->sem_nsems != PSEMS) { - tst_resm(TFAIL, "# of semaphores in set != # given to create"); - return; - } + sem_id = TST_RET; + check_functionality(); - if (un_arg.buf->sem_perm.cuid != geteuid()) { - tst_resm(TFAIL, "semaphore uid != process uid"); - return; - } - - tst_resm(TPASS, "basic semaphore values are okay"); + SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID); } -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) +static void setup(void) { - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - /* - * Create a temporary directory and cd into it. - * This helps to ensure that a unique msgkey is created. - * See libs/libltpipc/libipc.c for more information. - */ - tst_tmpdir(); - - /* get an IPC resource key */ - semkey = getipckey(); + sem_key = GETIPCKEY(); } -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) +static void cleanup(void) { - /* if it exists, remove the semaphore resouce */ - rm_sema(sem_id_1); - - tst_rmdir(); - + if (sem_id != -1) + SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .setup = setup, + .cleanup = cleanup, + .test_all = verify_semget, +}; diff --git a/testcases/kernel/syscalls/ipc/semget/semget02.c b/testcases/kernel/syscalls/ipc/semget/semget02.c index 4124514c2..4273c84c7 100644 --- a/testcases/kernel/syscalls/ipc/semget/semget02.c +++ b/testcases/kernel/syscalls/ipc/semget/semget02.c @@ -1,165 +1,102 @@ +// 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 */ -/* - * NAME - * semget02.c +/*\ + * [Description] * - * DESCRIPTION - * semget02 - test for EACCES and EEXIST errors + * This basic error handing of the semget syscall. * - * ALGORITHM - * create a semaphore set without read or alter permissions - * loop if that option was specified - * call semget() using two different invalid cases - * check the errno value - * issue a PASS message if we get EACCES or EEXIST - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * semget02 [-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. - * - * HISTORY - * 03/2001 - Written by Wayne Boyer - * - * RESTRICTIONS - * none + * - EACCES - a semaphore set exists for key, but the calling process does not + * have permission to access the set + * - EEXIST - a semaphore set already exists for key and IPC_CREAT | IPC_EXCL + * is given + * - ENOENT - No semaphore set exists for key and semflg did not specify + * IPC_CREAT + * - EINVAL - nsems is less than 0 or greater than the limit on the number of + * semaphores per semaphore set(SEMMSL) + * - EINVAL - a semaphore set corresponding to key already exists, but nsems is + * larger than the number of semaphores in that set */ -#include <pwd.h> - -#include "ipcsem.h" -char *TCID = "semget02"; -int TST_TOTAL = 2; - -char nobody_uid[] = "nobody"; -struct passwd *ltpuser; - -int sem_id_1 = -1; - -struct test_case_t { +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/types.h> +#include <pwd.h> +#include "tst_test.h" +#include "tst_safe_sysv_ipc.h" +#include "libnewipc.h" +#include "lapi/sem.h" + +static int sem_id = -1; +static key_t semkey, semkey1; +static struct passwd *pw; +static struct tcase { + int *key; + int nsems; int flags; - int error; -} TC[] = { - /* EACCES - the semaphore has no read or alter permissions */ - { - SEM_RA, EACCES}, - /* EEXIST - the semaphore id exists and semget() was called with */ - /* IPC_CREAT and IPC_EXCL */ - { - IPC_CREAT | IPC_EXCL, EEXIST} + int exp_err; + /*1: nobody expected, 0: root expected */ + int exp_user; +} tcases[] = { + {&semkey, PSEMS, SEM_RA, EACCES, 1}, + {&semkey, PSEMS, IPC_CREAT | IPC_EXCL, EEXIST, 0}, + {&semkey1, PSEMS, SEM_RA, ENOENT, 0}, + {&semkey1, -1, IPC_CREAT | IPC_EXCL, EINVAL, 0}, + {&semkey1, SEMMSL + 1, IPC_CREAT | IPC_EXCL, EINVAL, 0}, + {&semkey, PSEMS + 1, SEM_RA, EINVAL, 0}, }; -int main(int ac, char **av) +static void verify_semget(struct tcase *tc) { - int lc; - int i; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); /* global setup */ - - /* The following loop checks looping state if -i option given */ - - for (lc = 0; TEST_LOOPING(lc); lc++) { - /* reset tst_count in case we are looping */ - tst_count = 0; - - for (i = 0; i < TST_TOTAL; i++) { - /* use the TEST macro to make the call */ - - TEST(semget(semkey, PSEMS, TC[i].flags)); - - if (TEST_RETURN != -1) { - sem_id_1 = TEST_RETURN; - tst_resm(TFAIL, "call succeeded"); - continue; - } + TST_EXP_FAIL2(semget(*tc->key, tc->nsems, tc->flags), tc->exp_err, + "semget(%i, %i, %i)", *tc->key, tc->nsems, tc->flags); +} - if (TEST_ERRNO == TC[i].error) { - tst_resm(TPASS, "expected failure - errno " - "= %d : %s", TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - tst_resm(TFAIL, "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - } +static void do_test(unsigned int n) +{ + pid_t pid; + struct tcase *tc = &tcases[n]; + + if (tc->exp_user == 0) { + verify_semget(tc); + } else { + pid = SAFE_FORK(); + if (pid) { + tst_reap_children(); + } else { + SAFE_SETUID(pw->pw_uid); + verify_semget(tc); + exit(0); } } - - cleanup(); - - tst_exit(); } -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) +static void setup(void) { - tst_require_root(); - - /* Switch to nobody user for correct error code collection */ - ltpuser = getpwnam(nobody_uid); - if (seteuid(ltpuser->pw_uid) == -1) { - tst_resm(TINFO, "setreuid failed to " - "to set the effective uid to %d", ltpuser->pw_uid); - perror("setreuid"); - } - - tst_sig(NOFORK, DEF_HANDLER, cleanup); + semkey = GETIPCKEY(); + semkey1 = GETIPCKEY(); - TEST_PAUSE; + sem_id = SAFE_SEMGET(semkey, PSEMS, IPC_CREAT | IPC_EXCL); - /* - * Create a temporary directory and cd into it. - * This helps to ensure that a unique msgkey is created. - * See libs/libltpipc/libipc.c for more information. - */ - tst_tmpdir(); - - /* get an IPC resource key */ - semkey = getipckey(); - - /* create a semaphore set without read or alter permissions */ - if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL)) == -1) { - tst_brkm(TBROK, cleanup, "couldn't create semaphore in setup"); - } + pw = SAFE_GETPWNAM("nobody"); } -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) +static void cleanup(void) { - /* if it exists, remove the semaphore resource */ - rm_sema(sem_id_1); - - tst_rmdir(); - + if (sem_id != -1) + SAFE_SEMCTL(sem_id, PSEMS, IPC_RMID); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .needs_root = 1, + .forks_child = 1, + .tcnt = ARRAY_SIZE(tcases), + .setup = setup, + .cleanup = cleanup, + .test = do_test, +}; diff --git a/testcases/kernel/syscalls/ipc/semget/semget03.c b/testcases/kernel/syscalls/ipc/semget/semget03.c deleted file mode 100644 index 995b4bd3a..000000000 --- a/testcases/kernel/syscalls/ipc/semget/semget03.c +++ /dev/null @@ -1,133 +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 - * semget03.c - * - * DESCRIPTION - * semget03 - test for ENOENT error - * - * ALGORITHM - * loop if that option was specified - * call semget() with a valid key but with no associated semaphore set - * and IPC_CREAT is not asserted - * check the errno value - * issue a PASS message if we get ENOENT - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * semget03 [-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. - * - * HISTORY - * 03/2001 - Written by Wayne Boyer - * - * RESTRICTIONS - * none - */ - -#include "ipcsem.h" - -char *TCID = "semget03"; -int TST_TOTAL = 1; - -int sem_id_1 = -1; - -int main(int ac, char **av) -{ - int lc; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); /* global setup */ - - /* The following loop checks looping state if -i option given */ - - for (lc = 0; TEST_LOOPING(lc); lc++) { - /* reset tst_count in case we are looping */ - tst_count = 0; - - /* use the TEST macro to make the call */ - - TEST(semget(semkey, PSEMS, SEM_RA)); - - if (TEST_RETURN != -1) { - sem_id_1 = TEST_RETURN; - tst_resm(TFAIL, "call succeeded when error expected"); - continue; - } - - switch (TEST_ERRNO) { - case ENOENT: - tst_resm(TPASS, "expected failure - errno " - "= %d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); - break; - default: - tst_resm(TFAIL, "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } - } - - cleanup(); - - tst_exit(); -} - -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) -{ - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - /* - * Create a temporary directory and cd into it. - * This helps to ensure that a unique msgkey is created. - * See libs/libltpipc/libipc.c for more information. - */ - tst_tmpdir(); - - /* get an IPC resource key */ - semkey = getipckey(); -} - -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) -{ - /* if it exists, remove the semaphore resource */ - rm_sema(sem_id_1); - - tst_rmdir(); - -} diff --git a/testcases/kernel/syscalls/ipc/semget/semget05.c b/testcases/kernel/syscalls/ipc/semget/semget05.c index f801cb8ed..dd9a6285d 100644 --- a/testcases/kernel/syscalls/ipc/semget/semget05.c +++ b/testcases/kernel/syscalls/ipc/semget/semget05.c @@ -1,152 +1,83 @@ +// 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 */ -/* - * NAME - * semget05.c - * - * DESCRIPTION - * semget05 - test for ENOSPC error +/*\ + * [Description] * - * ALGORITHM - * create semaphore sets in a loop until the system limit is reached - * loop if that option was specified - * attempt to create yet another semaphore set - * check the errno value - * issue a PASS message if we get ENOSPC - * otherwise, the tests fails - * issue a FAIL message - * call cleanup + * Test for ENOSPC error. * - * USAGE: <for command-line> - * HISTORY - * 03/2001 - Written by Wayne Boyer - * 07/2006 - Changes By Michael Reed - * - Changed the value of MAXIDS for the specific machine by reading - * the system limit for SEMMNI - The maximum number of sempahore sets - * 03/2008 - Matthieu Fertré (mfertre@irisa.fr) - * - Fix concurrency issue. Create private semaphores to - * avoid conflict with concurrent processes. - * - * RESTRICTIONS - * none - */ - -#include "ipcsem.h" - -char *TCID = "semget05"; -int TST_TOTAL = 1; - -/* - * The MAXIDS value is somewhat arbitrary and may need to be increased - * depending on the system being tested. + * ENOSPC - a semaphore set exceed the maximum number of semaphore sets(SEMMNI) */ -int MAXIDS = 2048; - -int *sem_id_arr = NULL; -int num_sems = 0; /* count the semaphores created */ - -int main(int ac, char **av) +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include "lapi/sem.h" +#include "tst_test.h" +#include "libnewipc.h" +#include "tst_safe_sysv_ipc.h" + +static int *sem_id_arr; +static int maxsems, array_cnt, used_cnt; +static key_t semkey; + +static void verify_semget(void) { - int lc; - FILE *fp; - - tst_parse_opts(ac, av, NULL, NULL); - - /* Set the MAXIDS for the specific machine by reading the system limit - * for SEMMNI - The maximum number of sempahore sets - */ - fp = fopen("/proc/sys/kernel/sem", "r"); - if (fp != NULL) { - int getmaxid; - if (fscanf(fp, "%*d %*d %*d %d", &getmaxid) == 1) - MAXIDS = getmaxid + 1; - fclose(fp); - } - - sem_id_arr = malloc(sizeof(int) * MAXIDS); - if (sem_id_arr == NULL) - tst_brkm(TBROK, cleanup, "malloc failed"); - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - tst_count = 0; - - - TEST(semget(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)); - if (TEST_RETURN != -1) { - tst_resm(TFAIL, "call succeeded when error expected"); - continue; - } - - switch (TEST_ERRNO) { - case ENOSPC: - tst_resm(TPASS, "expected failure - errno " - "= %d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); - break; - default: - tst_resm(TFAIL, "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } - } - - cleanup(); - - tst_exit(); + TST_EXP_FAIL2(semget(semkey + maxsems, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA), + ENOSPC, "semget(%i, %i, %i)", semkey + maxsems, PSEMS, + IPC_CREAT | IPC_EXCL | SEM_RA); } -void setup(void) +static void setup(void) { - int sem_q; + int res, num; - tst_sig(NOFORK, DEF_HANDLER, cleanup); + semkey = GETIPCKEY(); + used_cnt = GET_USED_ARRAYS(); + tst_res(TINFO, "Current environment %d semaphore arrays are already in use", + used_cnt); + SAFE_FILE_SCANF("/proc/sys/kernel/sem", "%*d %*d %*d %d", &maxsems); - TEST_PAUSE; + /* Prevent timeout due to high semaphore array limit */ + tst_set_max_runtime(maxsems / 200); - tst_tmpdir(); - - while ((sem_q = semget(IPC_PRIVATE, PSEMS, IPC_CREAT | IPC_EXCL)) != -1) { - sem_id_arr[num_sems++] = sem_q; - if (num_sems == MAXIDS) { - tst_brkm(TBROK, cleanup, "The maximum number of " - "semaphore ID's has been\n\t reached. Please " - "increase the MAXIDS value in the test."); - } - } + sem_id_arr = SAFE_MALLOC((maxsems - used_cnt) * sizeof(int)); + for (num = 0; num < maxsems - used_cnt; num++) { + res = semget(semkey + num, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); + if (res == -1) + tst_brk(TBROK | TERRNO, "semget failed unexpectedly"); - if (errno != ENOSPC) { - tst_brkm(TBROK, cleanup, "Didn't get ENOSPC in test setup" - " - errno = %d : %s", errno, strerror(errno)); + sem_id_arr[array_cnt++] = res; } + tst_res(TINFO, "The maximum number of semaphore arrays (%d) has been reached", + maxsems); } -void cleanup(void) +static void cleanup(void) { - int i; + int num; - for (i = 0; i < num_sems; i++) { - rm_sema(sem_id_arr[i]); - } + if (!sem_id_arr) + return; + + for (num = 0; num < array_cnt; num++) + SAFE_SEMCTL(sem_id_arr[num], PSEMS, IPC_RMID); free(sem_id_arr); - tst_rmdir(); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .setup = setup, + .cleanup = cleanup, + .test_all = verify_semget, + .save_restore = (const struct tst_path_val[]){ + {"/proc/sys/kernel/sem", NULL, + TST_SR_TCONF_MISSING | TST_SR_SKIP_RO}, + {} + } +}; diff --git a/testcases/kernel/syscalls/ipc/semget/semget06.c b/testcases/kernel/syscalls/ipc/semget/semget06.c deleted file mode 100644 index 52297c010..000000000 --- a/testcases/kernel/syscalls/ipc/semget/semget06.c +++ /dev/null @@ -1,143 +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 - * semget06.c - * - * DESCRIPTION - * semget06 - test for EINVAL error - * - * ALGORITHM - * loop if that option was specified - * call semget() using two different invalid cases - too many and too - * few primitive semaphores - * check the errno value - * issue a PASS message if we get EINVAL - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * semget06 [-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. - * - * HISTORY - * 03/2001 - Written by Wayne Boyer - * - * RESTRICTIONS - * none - */ - -#include "ipcsem.h" - -char *TCID = "semget06"; -int TST_TOTAL = 2; - -#define LARGENUM 1024 * 32 -#define SMALLNUM -1 - -int sem_id_1 = -1; - -int num_sems[] = { LARGENUM, SMALLNUM }; - -int main(int ac, char **av) -{ - int lc; - int i; - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); /* global setup */ - - /* The following loop checks looping state if -i option given */ - - for (lc = 0; TEST_LOOPING(lc); lc++) { - /* reset tst_count in case we are looping */ - tst_count = 0; - - /* loop through the test cases */ - - for (i = 0; i < TST_TOTAL; i++) { - TEST(semget(semkey, num_sems[i], - IPC_CREAT | IPC_EXCL | SEM_RA)); - - if (TEST_RETURN != -1) { - sem_id_1 = TEST_RETURN; - tst_resm(TFAIL, "call succeeded"); - continue; - } - - switch (TEST_ERRNO) { - case EINVAL: - tst_resm(TPASS, "expected failure - errno " - "= %d : %s", TEST_ERRNO, - strerror(TEST_ERRNO)); - break; - default: - tst_resm(TFAIL, "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } - } - } - - cleanup(); - - tst_exit(); -} - -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) -{ - - tst_sig(NOFORK, DEF_HANDLER, cleanup); - - TEST_PAUSE; - - /* - * Create a temporary directory and cd into it. - * This helps to ensure that a unique msgkey is created. - * See libs/libltpipc/libipc.c for more information. - */ - tst_tmpdir(); - - /* get an IPC resource key */ - semkey = getipckey(); -} - -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) -{ - /* if it exists, remove the semaphore resource */ - rm_sema(sem_id_1); - - tst_rmdir(); - -} diff --git a/testcases/kernel/syscalls/ipc/semop/.gitignore b/testcases/kernel/syscalls/ipc/semop/.gitignore index bb57f08af..cc67b1862 100644 --- a/testcases/kernel/syscalls/ipc/semop/.gitignore +++ b/testcases/kernel/syscalls/ipc/semop/.gitignore @@ -1,3 +1,5 @@ /semop01 /semop02 /semop03 +/semop04 +/semop05 diff --git a/testcases/kernel/syscalls/ipc/semop/Makefile b/testcases/kernel/syscalls/ipc/semop/Makefile index 6b2b26d05..43afffb3f 100644 --- a/testcases/kernel/syscalls/ipc/semop/Makefile +++ b/testcases/kernel/syscalls/ipc/semop/Makefile @@ -7,6 +7,9 @@ LTPLIBS = ltpnewipc include $(top_srcdir)/include/mk/testcases.mk -LTPLDLIBS = -lltpnewipc +semop01: LTPLDLIBS = -lltpnewipc +semop02: LTPLDLIBS = -lltpnewipc +semop03: LTPLDLIBS = -lltpnewipc +semop05: LDLIBS += -lpthread include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/ipc/semop/semop04.c b/testcases/kernel/syscalls/ipc/semop/semop04.c new file mode 100644 index 000000000..1f49e7740 --- /dev/null +++ b/testcases/kernel/syscalls/ipc/semop/semop04.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) International Business Machines Corp., 2001 + * Copyright (C) 2003-2023 Linux Test Project, Inc. + * Author: 2001 Paul Larson <plars@us.ibm.com> + * Modified: 2001 Manoj Iyer <manjo@ausin.ibm.com> + */ + +/*\ + * [Description] + * + * Creates a semaphore and two processes. The processes + * each go through a loop where they semdown, delay for a + * random amount of time, and semup, so they will almost + * always be fighting for control of the semaphore. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include "lapi/sem.h" +#include "tst_test.h" +#include "tst_safe_sysv_ipc.h" + +#define LOOPS 1000 +#define SEED 123 + +static void semup(int semid) +{ + struct sembuf semops; + + semops.sem_num = 0; + semops.sem_op = 1; + semops.sem_flg = SEM_UNDO; + + SAFE_SEMOP(semid, &semops, 1); +} + +static void semdown(int semid) +{ + struct sembuf semops; + + semops.sem_num = 0; + semops.sem_op = -1; + semops.sem_flg = SEM_UNDO; + + SAFE_SEMOP(semid, &semops, 1); +} + +static void mainloop(int semid) +{ + int i; + + for (i = 0; i < LOOPS; i++) { + semdown(semid); + usleep(1 + ((100.0 * rand()) / RAND_MAX)); + semup(semid); + } +} + +static void run(void) +{ + int semid; + union semun semunion; + pid_t pid; + + /* set up the semaphore */ + semid = SAFE_SEMGET((key_t) 9142, 1, 0666 | IPC_CREAT); + + semunion.val = 1; + + SAFE_SEMCTL(semid, 0, SETVAL, semunion); + + tst_res(TINFO, "srand seed is %d", SEED); + srand(SEED); + + pid = SAFE_FORK(); + + if (pid) { + mainloop(semid); + tst_reap_children(); + TST_EXP_POSITIVE(semctl(semid, 0, IPC_RMID, semunion)); + } else { + mainloop(semid); + } +} + +static struct tst_test test = { + .test_all = run, + .forks_child = 1, +}; diff --git a/testcases/kernel/syscalls/ipc/semop/semop05.c b/testcases/kernel/syscalls/ipc/semop/semop05.c new file mode 100644 index 000000000..34b714bf0 --- /dev/null +++ b/testcases/kernel/syscalls/ipc/semop/semop05.c @@ -0,0 +1,157 @@ +/* + * + * Copyright (c) International Business Machines Corp., 2002 + * + * 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 : sem02.c + * + * DESCRIPTION : The application creates several threads using pthread_create(). + * One thread performs a semop() with the SEM_UNDO flag set. The change in + * sempaphore value performed by that semop should be "undone" only when the + * last pthread exits. + * + * EXPECTED OUTPUT: + * Waiter, pid = <pid#> + * Poster, pid = <pid#>, posting + * Poster posted + * Poster exiting + * Waiter waiting, pid = <pid#> + * Waiter done waiting + * + * HISTORY: + * written by Dave Olien (oliend@us.ibm.com) + * 03/06/2002 Robbie Williamson (robbiew@us.ibm.com) + * -ported + * 07/04/2003 Paul Larson (plars@linuxtestproject.org) + * -ported to LTP + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include "lapi/sem.h" +#include "test.h" + +#define KEY IPC_PRIVATE + +#define NUMTHREADS 2 + +void *retval[NUMTHREADS]; +void *waiter(void *); +void *poster(void *); +void cleanup(void); + +char *TCID = "sem02"; +int TST_TOTAL = 1; + +struct sembuf Psembuf = { 0, -1, SEM_UNDO }; +struct sembuf Vsembuf = { 0, 1, SEM_UNDO }; + +int sem_id; +int err_ret; /* This is used to determine PASS/FAIL status */ +int main(int argc, char **argv) +{ + int i, rc; + union semun semunion; + + pthread_t pt[NUMTHREADS]; + pthread_attr_t attr; + + tst_parse_opts(argc, argv, NULL, NULL); + /* Create the semaphore set */ + sem_id = semget(KEY, 1, 0666 | IPC_CREAT); + if (sem_id < 0) { + printf("semget failed, errno = %d\n", errno); + exit(1); + } + /* initialize data structure associated to the semaphore */ + semunion.val = 1; + semctl(sem_id, 0, SETVAL, semunion); + + /* setup the attributes of the thread */ + /* set the scope to be system to make sure the threads compete on a */ + /* global scale for cpu */ + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + + err_ret = 1; /* Set initial error value to 1 */ + /* Create the threads */ + for (i = 0; i < NUMTHREADS; i++) { + if (i == 0) + rc = pthread_create(&pt[i], &attr, waiter, retval[i]); + else + rc = pthread_create(&pt[i], &attr, poster, retval[i]); + } + + /* Sleep long enough to see that the other threads do what they are supposed to do */ + sleep(20); + semunion.val = 1; + semctl(sem_id, 0, IPC_RMID, semunion); + if (err_ret == 1) + tst_resm(TFAIL, "failed"); + else + tst_resm(TPASS, "passed"); + cleanup(); + + tst_exit(); +} + +/* This thread sleeps 10 seconds then waits on the semaphore. As long + as someone has posted on the semaphore, and no undo has taken + place, the semop should complete and we'll print "Waiter done + waiting." */ +void *waiter(void *foo) +{ + int pid; + pid = getpid(); + + tst_resm(TINFO, "Waiter, pid = %d", pid); + sleep(10); + + tst_resm(TINFO, "Waiter waiting, pid = %d", pid); + semop(sem_id, &Psembuf, 1); + tst_resm(TINFO, "Waiter done waiting"); + err_ret = 0; /* If the message above is displayed, the test is a PASS */ + pthread_exit(0); +} + +/* This thread immediately posts on the semaphore and then immediately + exits. If the *thread* exits, the undo should not happen, and the + waiter thread which will start waiting on it in 10 seconds, should + still get it. */ +void *poster(void *foo) +{ + int pid; + + pid = getpid(); + tst_resm(TINFO, "Poster, pid = %d, posting", pid); + semop(sem_id, &Vsembuf, 1); + tst_resm(TINFO, "Poster posted"); + tst_resm(TINFO, "Poster exiting"); + + pthread_exit(0); +} + +void cleanup(void) +{ +} diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c index 3788e711f..8168803a5 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c @@ -11,17 +11,17 @@ * * Test for ENOENT, EEXIST, EINVAL, EACCES, EPERM errors. * - * ENOENT - No segment exists for the given key and IPC_CREAT was not specified. - * EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given. - * EINVAL - A new segment was to be created and size is less than SHMMIN or - * greater than SHMMAX. Or a segment for the given key exists, but size is - * gran eater than the size of that segment. - * EACCES - The user does not have permission to access the shared memory segment. - * EPERM - The SHM_HUGETLB flag was specified, but the caller was not privileged - * (did not have the CAP_IPC_LOCK capability) and is not a member of the - * sysctl_hugetlb_shm_group group. - * ENOMEM - The SHM_HUGETLB flag was specified, the caller was privileged but not - * have enough hugepage memory space. + * - ENOENT - No segment exists for the given key and IPC_CREAT was not specified. + * - EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given. + * - EINVAL - A new segment was to be created and size is less than SHMMIN or + * greater than SHMMAX. Or a segment for the given key exists, but size is + * gran eater than the size of that segment. + * - EACCES - The user does not have permission to access the shared memory segment. + * - EPERM - The SHM_HUGETLB flag was specified, but the caller was not + * privileged (did not have the CAP_IPC_LOCK capability) and is not a member + * of the sysctl_hugetlb_shm_group group. + * - ENOMEM - The SHM_HUGETLB flag was specified, the caller was privileged but + * not have enough hugepage memory space. */ #include <errno.h> @@ -56,7 +56,7 @@ static struct tcase { {&shmkey1, SHM_SIZE, IPC_EXCL, 0, 0, ENOENT}, {&shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL, 0, 0, EEXIST}, {&shmkey1, SHMMIN - 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL}, - {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL}, + {&shmkey1, 8192 + 1, IPC_CREAT | IPC_EXCL, 0, 0, EINVAL}, {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, 0, EINVAL}, {&shmkey, SHM_SIZE, SHM_RD, 1, 0, EACCES}, {&shmkey1, SHM_SIZE, IPC_CREAT | SHM_HUGETLB, 0, 1, EPERM}, @@ -149,4 +149,8 @@ static struct tst_test test = { .test = do_test, .tcnt = ARRAY_SIZE(tcases), .hugepages = {TST_NO_HUGEPAGES}, + .save_restore = (const struct tst_path_val[]) { + {"/proc/sys/kernel/shmmax", "8192", TST_SR_TCONF_MISSING | TST_SR_TBROK_RO}, + {} + }, }; |