Message ID | 1620809541-6891-2-git-send-email-xuyang2018.jy@fujitsu.com |
---|---|
State | Changes Requested |
Headers | show |
Series | [v1,1/4] syscalls/shmget01: Remove it | expand |
Hi ALL > 1) merge shmget05.c into shmget02.c > 2) Use SHMMIN -1 and SHMMAX + 1 to trigger EINVAL error > 3) Use SHM_RD, SHM_WR, SHM_RW to trigger EACCES error under unpriviledged user Sorry for missing EPERM error in shmget02.c(I will add it in v2 when you have comment on rest patches) diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c index a57904ce9..319d1e972 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c @@ -17,6 +17,9 @@ * greater than SHMMAX. Or a segment for the given key exists, but size is * greater 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). Also the caller's group id should + * be not in hugetlb_shm_group proc file. */ #include <errno.h> #include <sys/types.h> @@ -47,6 +50,7 @@ static struct tcase { {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, EINVAL}, {&shmkey, SHM_SIZE, SHM_RD, 1, EACCES}, + {&shmkey1, SHM_SIZE, IPC_CREAT | SHM_HUGETLB, 1, EPERM} }; static void verify_shmget(struct tcase *tc) @@ -91,6 +95,7 @@ static void setup(void) shmkey = GETIPCKEY(); shmkey1 = GETIPCKEY(); + SAFE_FILE_PRINTF("/proc/sys/vm/hugetlb_shm_group", "1"); shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); pw = SAFE_GETPWNAM("nobody"); tst_res(TINFO, "%d %d", shmkey, shmkey1); @@ -110,4 +115,8 @@ static struct tst_test test = { .cleanup = cleanup, .test = do_test, .tcnt = ARRAY_SIZE(tcases), + .save_restore = (const char * const[]) { + "?/proc/sys/vm/hugetlb_shm_group", + NULL, + } };
Hi! Ping. Also add a url[1] for the missing EPRERM error(should see lastest man-page). [1]https://github.com/mkerrisk/man-pages/commit/090fdddb4342f92a1dbeba687462f4bcee816232 Best Regards Yang Xu > Hi ALL >> 1) merge shmget05.c into shmget02.c >> 2) Use SHMMIN -1 and SHMMAX + 1 to trigger EINVAL error >> 3) Use SHM_RD, SHM_WR, SHM_RW to trigger EACCES error under unpriviledged user > > Sorry for missing EPERM error in shmget02.c(I will add it in v2 when you > have comment on rest patches) > > diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget02.c > b/testcases/kernel/syscalls/ipc/shmget/shmget02.c > index a57904ce9..319d1e972 100644 > --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c > +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c > @@ -17,6 +17,9 @@ > * greater than SHMMAX. Or a segment for the given key exists, but size is > * greater 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). Also the caller's group > id should > + * be not in hugetlb_shm_group proc file. > */ > #include<errno.h> > #include<sys/types.h> > @@ -47,6 +50,7 @@ static struct tcase { > {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, > {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, EINVAL}, > {&shmkey, SHM_SIZE, SHM_RD, 1, EACCES}, > + {&shmkey1, SHM_SIZE, IPC_CREAT | SHM_HUGETLB, 1, EPERM} > }; > > static void verify_shmget(struct tcase *tc) > @@ -91,6 +95,7 @@ static void setup(void) > shmkey = GETIPCKEY(); > shmkey1 = GETIPCKEY(); > > + SAFE_FILE_PRINTF("/proc/sys/vm/hugetlb_shm_group", "1"); > shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); > pw = SAFE_GETPWNAM("nobody"); > tst_res(TINFO, "%d %d", shmkey, shmkey1); > @@ -110,4 +115,8 @@ static struct tst_test test = { > .cleanup = cleanup, > .test = do_test, > .tcnt = ARRAY_SIZE(tcases), > + .save_restore = (const char * const[]) { > + "?/proc/sys/vm/hugetlb_shm_group", > + NULL, > + } > }; >
Hi! > 1) merge shmget05.c into shmget02.c > 2) Use SHMMIN -1 and SHMMAX + 1 to trigger EINVAL error > 3) Use SHM_RD, SHM_WR, SHM_RW to trigger EACCES error under unpriviledged user > > Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com> > --- > include/lapi/shm.h | 14 + > runtest/syscalls | 1 - > runtest/syscalls-ipc | 1 - > .../kernel/syscalls/ipc/shmget/.gitignore | 1 - > testcases/kernel/syscalls/ipc/shmget/Makefile | 4 +- > .../kernel/syscalls/ipc/shmget/shmget02.c | 243 +++++++----------- > .../kernel/syscalls/ipc/shmget/shmget03.c | 199 ++++---------- > .../kernel/syscalls/ipc/shmget/shmget04.c | 193 +++++--------- > .../kernel/syscalls/ipc/shmget/shmget05.c | 185 ------------- > 9 files changed, 209 insertions(+), 632 deletions(-) > delete mode 100644 testcases/kernel/syscalls/ipc/shmget/shmget05.c > > diff --git a/include/lapi/shm.h b/include/lapi/shm.h > index 61c4e37bf..bb280fc44 100644 > --- a/include/lapi/shm.h > +++ b/include/lapi/shm.h > @@ -6,8 +6,22 @@ > #ifndef LAPI_SHM_H__ > #define LAPI_SHM_H__ > > +#include <limits.h> > + > #ifndef SHM_STAT_ANY > # define SHM_STAT_ANY 15 > #endif > > +#ifndef SHMMIN > +# define SHMMIN 1 > +#endif > + > +#ifndef SHMMAX > +# define SHMMAX (ULONG_MAX - (1UL << 24)) > +#endif > + > +#ifndef SHMMNI > +# define SHMMNI 4096 > +#endif > + > #endif /* LAPI_SHM_H__ */ > diff --git a/runtest/syscalls b/runtest/syscalls > index 63d821e53..2dff25984 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -1402,7 +1402,6 @@ shmdt02 shmdt02 > shmget02 shmget02 > shmget03 shmget03 > shmget04 shmget04 > -shmget05 shmget05 > > sigaction01 sigaction01 > sigaction02 sigaction02 > diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc > index ff0364704..b3bd37923 100644 > --- a/runtest/syscalls-ipc > +++ b/runtest/syscalls-ipc > @@ -67,4 +67,3 @@ shmdt02 shmdt02 > shmget02 shmget02 > shmget03 shmget03 > shmget04 shmget04 > -shmget05 shmget05 > diff --git a/testcases/kernel/syscalls/ipc/shmget/.gitignore b/testcases/kernel/syscalls/ipc/shmget/.gitignore > index 6f08529f8..c57df68f5 100644 > --- a/testcases/kernel/syscalls/ipc/shmget/.gitignore > +++ b/testcases/kernel/syscalls/ipc/shmget/.gitignore > @@ -1,4 +1,3 @@ > /shmget02 > /shmget03 > /shmget04 > -/shmget05 > diff --git a/testcases/kernel/syscalls/ipc/shmget/Makefile b/testcases/kernel/syscalls/ipc/shmget/Makefile > index 26b9f264d..b1201281d 100644 > --- a/testcases/kernel/syscalls/ipc/shmget/Makefile > +++ b/testcases/kernel/syscalls/ipc/shmget/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/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c > index 4436ca7f8..a57904ce9 100644 > --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c > +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c > @@ -1,184 +1,113 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > /* > + * Copyright (c) International Business Machines Corp., 2001 > + * 03/2001 - Written by Wayne Boyer > * > - * 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) 2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) > */ > > -/* > - * NAME > - * shmget02.c > - * > - * DESCRIPTION > - * shmget02 - check for ENOENT, EEXIST and EINVAL errors > +/*\ > + * [Description] > * > - * ALGORITHM > - * create a shared memory segment with read & write permissions > - * loop if that option was specified > - * call shmget() using five different invalid cases > - * check the errno value > - * issue a PASS message if we get ENOENT, EEXIST or EINVAL > - * otherwise, the tests fails > - * issue a FAIL message > - * call cleanup > + * Test for ENOENT, EEXIST, EINVAL, EACCES errors. > * > - * USAGE: <for command-line> > - * shmget02 [-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 > - * > - * 06/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) > - * - Fix concurrency issue. The second key used for this test could > - * conflict with the key from another task. > - * > - * RESTRICTIONS > - * none > + * 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 > + * greater than the size of that segment. > + * EACCES - The user does not have permission to access the shared memory segment. > */ > - > -#include "ipcshm.h" > - > -char *TCID = "shmget02"; > -int TST_TOTAL = 4; > - > -int shm_id_1 = -1; > -int shm_nonexisting_key = -1; > -key_t shmkey2; > - > -struct test_case_t { > - int *skey; > - int size; > +#include <errno.h> > +#include <sys/types.h> > +#include <sys/ipc.h> > +#include <stdlib.h> > +#include <pwd.h> > +#include <sys/shm.h> > +#include "tst_safe_sysv_ipc.h" > +#include "tst_test.h" > +#include "libnewipc.h" > +#include "lapi/shm.h" > + > +static int shm_id = -1; > +static key_t shmkey, shmkey1; > +static struct passwd *pw; > + > +static struct tcase { > + int *shmkey; > + size_t size; > int flags; > - int error; > -} TC[] = { > - /* EINVAL - size is 0 */ > - { > - &shmkey2, 0, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, > - /* EINVAL - size is negative */ > -// {&shmkey2, -1, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, > - /* EINVAL - size is larger than created segment */ > - { > - &shmkey, SHM_SIZE * 2, SHM_RW, EINVAL}, > - /* EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given */ > - { > - &shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW, EEXIST}, > - /* ENOENT - no segment exists for the key and IPC_CREAT is not given */ > - /* use shm_id_2 (-1) as the key */ > - { > - &shm_nonexisting_key, SHM_SIZE, SHM_RW, ENOENT} > + /*1: nobody expected 0: root expected */ > + int exp_user; > + int exp_err; > +} tcases[] = { > + {&shmkey1, SHM_SIZE, IPC_EXCL, 0, ENOENT}, > + {&shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL, 0, EEXIST}, > + {&shmkey1, SHMMIN - 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, > + {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, Can we please add the zero size EINVAL test as well? > + {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, EINVAL}, > + {&shmkey, SHM_SIZE, SHM_RD, 1, EACCES}, > }; ... > +static void do_test(unsigned int n) > { > + struct tcase *tc = &tcases[n]; > + pid_t pid; > > - 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 */ > - shmkey = getipckey(); > - > - /* Get an new IPC resource key. */ > - shmkey2 = getipckey(); > - > - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | > - SHM_RW)) == -1) { > - tst_brkm(TBROK, cleanup, "couldn't create shared memory " > - "segment in setup()"); > + if (tc->exp_user == 0) { > + verify_shmget(tc); Just use the TST_EXP_FAIL() macro here instead, no need to reinvent the wheel. > + return; > } > > - /* Make sure shm_nonexisting_key is a nonexisting key */ > - while (1) { > - while (-1 != shmget(shm_nonexisting_key, 1, SHM_RD)) { > - shm_nonexisting_key--; > - } > - if (errno == ENOENT) > - break; > + pid = SAFE_FORK(); > + if (pid == 0) { > + SAFE_SETUID(pw->pw_uid); > + verify_shmget(tc); And here as well. > + exit(0); > } > + tst_reap_children(); > } > > -/* > - * cleanup() - performs all the ONE TIME cleanup for this test at completion > - * or premature exit. > - */ > -void cleanup(void) > +static void setup(void) > { > - /* if it exists, remove the shared memory resource */ > - rm_shm(shm_id_1); > + shmkey = GETIPCKEY(); > + shmkey1 = GETIPCKEY(); > > - tst_rmdir(); > + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); > + pw = SAFE_GETPWNAM("nobody"); > + tst_res(TINFO, "%d %d", shmkey, shmkey1); I'm not sure if this message is useful. > +} > > +static void cleanup(void) > +{ > + if (shm_id >= 0) > + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); > } > + > +static struct tst_test test = { > + .needs_tmpdir = 1, > + .needs_root = 1, > + .forks_child = 1, > + .setup = setup, > + .cleanup = cleanup, > + .test = do_test, > + .tcnt = ARRAY_SIZE(tcases), > +}; > diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget03.c b/testcases/kernel/syscalls/ipc/shmget/shmget03.c > index 96ebf3608..c74fe241d 100644 > --- a/testcases/kernel/syscalls/ipc/shmget/shmget03.c > +++ b/testcases/kernel/syscalls/ipc/shmget/shmget03.c > @@ -1,171 +1,68 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later ... > +static int shm_id_arr[SHMMNI] = {-1}; The SHMMNI is just default value, it could be adjusted at runtime by setting /proc/sys/kernel/shmmni So we should ideally fix the test to read that value in the test setup and allocate the array based on the value. > +static void verify_shmget(void) > { > - 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(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL > - | SHM_RW)); > - > - 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, "call failed with an " > - "unexpected error - %d : %s", > - TEST_ERRNO, strerror(TEST_ERRNO)); > - break; > - } > + TEST(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW)); > + if (TST_RET != -1) { > + tst_res(TFAIL, "shmget() returned %li", TST_RET); > + return; > } > - > - cleanup(); > - > - tst_exit(); > + if (TST_ERR == ENOSPC) > + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); > + else > + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected ENOSPC, bug got"); This should be TST_EXP_FAIL() as well. > } > > -/* > - * setup() - performs all the ONE TIME setup for this test. > - */ > -void setup(void) > +static void setup(void) > { > + int res, num; > > - 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 */ > - shmkey = getipckey(); > - > - /* > - * Use a while loop to create the maximum number of memory segments. > - * If the loop exceeds MAXIDS, then break the test and cleanup. > - */ > - while ((shm_id_1 = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | > - IPC_EXCL | SHM_RW)) != -1) { > - shm_id_arr[num_shms++] = shm_id_1; > - if (num_shms == MAXIDS) { > - tst_brkm(TBROK, cleanup, "The maximum number of shared " > - "memory ID's has been\n\t reached. Please " > - "increase the MAXIDS value in the test."); > - } > - } > - > - /* > - * If the errno is other than ENOSPC, then something else is wrong. > - */ > - if (errno != ENOSPC) { > - tst_resm(TINFO, "errno = %d : %s", errno, strerror(errno)); > - tst_brkm(TBROK, cleanup, "Didn't get ENOSPC in test setup"); > + for (num = 0; num < SHMMNI; num++) { > + res = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW); > + if (res != -1) > + shm_id_arr[num] = res; > } So we attempt to allocate SHMMNI shared memory segemnts and the last call will fail. I guess that we can as well attempt to allocate SHMMNI-1 segemnts and expect them to all pass. I do not like ignore any failures that may happen here and cary on with the test. It would be better to TBROK here instead. > + tst_res(TINFO, "The maximum number(%d) of memory ID's has been reached", > + SHMMNI); > } > > -/* > - * cleanup() - performs all the ONE TIME cleanup for this test at completion > - * or premature exit. > - */ > -void cleanup(void) > + > +static void cleanup(void) > { > int i; > > - /* remove the shared memory resources that were created */ > - for (i = 0; i < num_shms; i++) { > - rm_shm(shm_id_arr[i]); > + for (i = 0; i < SHMMNI; i++) { > + if (shm_id_arr[i] >= 0) This is actually not correct, since there are possibly zeros in the array (just because it's global variable and only first position is intialized wiht -1) and we could incorrectly attempt to remove sement with id 0. I guess that the cleanest way how to handle this would be having global counter for the number of created semgents: static key_t *keys; static unsigned int max_key; setup() { ... keys = SAFE_MALLOC(sizeof(key_t) * shmmni); ... for (;;) { if (max_key >= shmni) break; keys[max_key] = shmget(...); if (keys[max_key] < 0) tst_brk(TBROK, ...); max_key++; } } cleanup() { key_t key; for (key = 0; key < max_key; key++) SAFE_SHMCTL(keys[key], IPC_RMID, NULL); } > + SAFE_SHMCTL(shm_id_arr[i], IPC_RMID, NULL); > } > - > - tst_rmdir(); > - > } > + > +static struct tst_test test = { > + .setup = setup, > + .cleanup = cleanup, > + .test_all = verify_shmget, > +}; > diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget04.c b/testcases/kernel/syscalls/ipc/shmget/shmget04.c > index 60a263c77..fe611b306 100644 ... > + tst_res(TINFO, "%s", tc->message); > + TEST(shmget(shmkey, SHM_SIZE, tc->flag)); > + if (TST_RET != -1) { > + tst_res(TFAIL, "shmget() returned %li", TST_RET); > + return; > } > - > - cleanup(); > - > - tst_exit(); > + if (TST_ERR == EACCES) > + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); > + else > + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected EACCES, bug got"); TST_EXP_FAIL() here as well. > } > > -/* > - * setup() - performs all the ONE TIME setup for this test. > - */ > -void setup(void) > +static void setup(void) > { > - tst_require_root(); > - > - tst_sig(NOFORK, DEF_HANDLER, cleanup); > + struct passwd *pw; > > - TEST_PAUSE; > - > - /* Switch to nobody user for correct error code collection */ > - ltpuser = getpwnam(nobody_uid); > - if (setuid(ltpuser->pw_uid) == -1) { > - tst_resm(TINFO, "setuid failed to " > - "to set the effective uid to %d", ltpuser->pw_uid); > - perror("setuid"); > - } > + pw = SAFE_GETPWNAM("nobody"); > + SAFE_SETUID(pw->pw_uid); > + shmkey = GETIPCKEY(); > > - /* > - * 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 */ > - shmkey = getipckey(); > - > - /* create a shared memory segment without read or access permissions */ > - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL)) == -1) { > - tst_brkm(TBROK, cleanup, "Failed to create shared memory " > - "segment in setup"); > - } > + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); > } > > -/* > - * 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 shared memory resource */ > - rm_shm(shm_id_1); > - > - tst_rmdir(); > - > + if (shm_id >= 0) > + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); > } > + > +static struct tst_test test = { > + .needs_tmpdir = 1, > + .needs_root = 1, > + .setup = setup, > + .cleanup = cleanup, > + .test = verify_shmget, > + .tcnt = ARRAY_SIZE(tcases), > +};
Hi Cyril Thanks for your review, will fix these comments on v2. > Hi! >> 1) merge shmget05.c into shmget02.c >> 2) Use SHMMIN -1 and SHMMAX + 1 to trigger EINVAL error >> 3) Use SHM_RD, SHM_WR, SHM_RW to trigger EACCES error under unpriviledged user >> >> Signed-off-by: Yang Xu<xuyang2018.jy@fujitsu.com> >> --- >> include/lapi/shm.h | 14 + >> runtest/syscalls | 1 - >> runtest/syscalls-ipc | 1 - >> .../kernel/syscalls/ipc/shmget/.gitignore | 1 - >> testcases/kernel/syscalls/ipc/shmget/Makefile | 4 +- >> .../kernel/syscalls/ipc/shmget/shmget02.c | 243 +++++++----------- >> .../kernel/syscalls/ipc/shmget/shmget03.c | 199 ++++---------- >> .../kernel/syscalls/ipc/shmget/shmget04.c | 193 +++++--------- >> .../kernel/syscalls/ipc/shmget/shmget05.c | 185 ------------- >> 9 files changed, 209 insertions(+), 632 deletions(-) >> delete mode 100644 testcases/kernel/syscalls/ipc/shmget/shmget05.c >> >> diff --git a/include/lapi/shm.h b/include/lapi/shm.h >> index 61c4e37bf..bb280fc44 100644 >> --- a/include/lapi/shm.h >> +++ b/include/lapi/shm.h >> @@ -6,8 +6,22 @@ >> #ifndef LAPI_SHM_H__ >> #define LAPI_SHM_H__ >> >> +#include<limits.h> >> + >> #ifndef SHM_STAT_ANY >> # define SHM_STAT_ANY 15 >> #endif >> >> +#ifndef SHMMIN >> +# define SHMMIN 1 >> +#endif >> + >> +#ifndef SHMMAX >> +# define SHMMAX (ULONG_MAX - (1UL<< 24)) >> +#endif >> + >> +#ifndef SHMMNI >> +# define SHMMNI 4096 >> +#endif >> + >> #endif /* LAPI_SHM_H__ */ >> diff --git a/runtest/syscalls b/runtest/syscalls >> index 63d821e53..2dff25984 100644 >> --- a/runtest/syscalls >> +++ b/runtest/syscalls >> @@ -1402,7 +1402,6 @@ shmdt02 shmdt02 >> shmget02 shmget02 >> shmget03 shmget03 >> shmget04 shmget04 >> -shmget05 shmget05 >> >> sigaction01 sigaction01 >> sigaction02 sigaction02 >> diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc >> index ff0364704..b3bd37923 100644 >> --- a/runtest/syscalls-ipc >> +++ b/runtest/syscalls-ipc >> @@ -67,4 +67,3 @@ shmdt02 shmdt02 >> shmget02 shmget02 >> shmget03 shmget03 >> shmget04 shmget04 >> -shmget05 shmget05 >> diff --git a/testcases/kernel/syscalls/ipc/shmget/.gitignore b/testcases/kernel/syscalls/ipc/shmget/.gitignore >> index 6f08529f8..c57df68f5 100644 >> --- a/testcases/kernel/syscalls/ipc/shmget/.gitignore >> +++ b/testcases/kernel/syscalls/ipc/shmget/.gitignore >> @@ -1,4 +1,3 @@ >> /shmget02 >> /shmget03 >> /shmget04 >> -/shmget05 >> diff --git a/testcases/kernel/syscalls/ipc/shmget/Makefile b/testcases/kernel/syscalls/ipc/shmget/Makefile >> index 26b9f264d..b1201281d 100644 >> --- a/testcases/kernel/syscalls/ipc/shmget/Makefile >> +++ b/testcases/kernel/syscalls/ipc/shmget/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/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c >> index 4436ca7f8..a57904ce9 100644 >> --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c >> +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c >> @@ -1,184 +1,113 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later >> /* >> + * Copyright (c) International Business Machines Corp., 2001 >> + * 03/2001 - Written by Wayne Boyer >> * >> - * 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) 2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) >> */ >> >> -/* >> - * NAME >> - * shmget02.c >> - * >> - * DESCRIPTION >> - * shmget02 - check for ENOENT, EEXIST and EINVAL errors >> +/*\ >> + * [Description] >> * >> - * ALGORITHM >> - * create a shared memory segment with read& write permissions >> - * loop if that option was specified >> - * call shmget() using five different invalid cases >> - * check the errno value >> - * issue a PASS message if we get ENOENT, EEXIST or EINVAL >> - * otherwise, the tests fails >> - * issue a FAIL message >> - * call cleanup >> + * Test for ENOENT, EEXIST, EINVAL, EACCES errors. >> * >> - * USAGE:<for command-line> >> - * shmget02 [-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 >> - * >> - * 06/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) >> - * - Fix concurrency issue. The second key used for this test could >> - * conflict with the key from another task. >> - * >> - * RESTRICTIONS >> - * none >> + * 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 >> + * greater than the size of that segment. >> + * EACCES - The user does not have permission to access the shared memory segment. >> */ >> - >> -#include "ipcshm.h" >> - >> -char *TCID = "shmget02"; >> -int TST_TOTAL = 4; >> - >> -int shm_id_1 = -1; >> -int shm_nonexisting_key = -1; >> -key_t shmkey2; >> - >> -struct test_case_t { >> - int *skey; >> - int size; >> +#include<errno.h> >> +#include<sys/types.h> >> +#include<sys/ipc.h> >> +#include<stdlib.h> >> +#include<pwd.h> >> +#include<sys/shm.h> >> +#include "tst_safe_sysv_ipc.h" >> +#include "tst_test.h" >> +#include "libnewipc.h" >> +#include "lapi/shm.h" >> + >> +static int shm_id = -1; >> +static key_t shmkey, shmkey1; >> +static struct passwd *pw; >> + >> +static struct tcase { >> + int *shmkey; >> + size_t size; >> int flags; >> - int error; >> -} TC[] = { >> - /* EINVAL - size is 0 */ >> - { >> - &shmkey2, 0, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, >> - /* EINVAL - size is negative */ >> -// {&shmkey2, -1, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, >> - /* EINVAL - size is larger than created segment */ >> - { >> - &shmkey, SHM_SIZE * 2, SHM_RW, EINVAL}, >> - /* EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given */ >> - { >> - &shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW, EEXIST}, >> - /* ENOENT - no segment exists for the key and IPC_CREAT is not given */ >> - /* use shm_id_2 (-1) as the key */ >> - { >> - &shm_nonexisting_key, SHM_SIZE, SHM_RW, ENOENT} >> + /*1: nobody expected 0: root expected */ >> + int exp_user; >> + int exp_err; >> +} tcases[] = { >> + {&shmkey1, SHM_SIZE, IPC_EXCL, 0, ENOENT}, >> + {&shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL, 0, EEXIST}, >> + {&shmkey1, SHMMIN - 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, >> + {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, > > Can we please add the zero size EINVAL test as well? SHMMIN is equal to 1, so we have tested zero size EINVAL test. > >> + {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, EINVAL}, >> + {&shmkey, SHM_SIZE, SHM_RD, 1, EACCES}, >> }; > > ... > >> +static void do_test(unsigned int n) >> { >> + struct tcase *tc =&tcases[n]; >> + pid_t pid; >> >> - 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 */ >> - shmkey = getipckey(); >> - >> - /* Get an new IPC resource key. */ >> - shmkey2 = getipckey(); >> - >> - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | >> - SHM_RW)) == -1) { >> - tst_brkm(TBROK, cleanup, "couldn't create shared memory " >> - "segment in setup()"); >> + if (tc->exp_user == 0) { >> + verify_shmget(tc); > > Just use the TST_EXP_FAIL() macro here instead, no need to reinvent the > wheel. Yes, use TST_EXP_FAIL(shmget(*tc->shmkey, tc->size, tc->flags), tc->exp_err, "shmget(%i, %lu, %i)",*tc->shmkey, tc->size, tc->flags) to replace. > >> + return; >> } >> >> - /* Make sure shm_nonexisting_key is a nonexisting key */ >> - while (1) { >> - while (-1 != shmget(shm_nonexisting_key, 1, SHM_RD)) { >> - shm_nonexisting_key--; >> - } >> - if (errno == ENOENT) >> - break; >> + pid = SAFE_FORK(); >> + if (pid == 0) { >> + SAFE_SETUID(pw->pw_uid); >> + verify_shmget(tc); > > And here as well. OK. > >> + exit(0); >> } >> + tst_reap_children(); >> } >> >> -/* >> - * cleanup() - performs all the ONE TIME cleanup for this test at completion >> - * or premature exit. >> - */ >> -void cleanup(void) >> +static void setup(void) >> { >> - /* if it exists, remove the shared memory resource */ >> - rm_shm(shm_id_1); >> + shmkey = GETIPCKEY(); >> + shmkey1 = GETIPCKEY(); >> >> - tst_rmdir(); >> + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); >> + pw = SAFE_GETPWNAM("nobody"); >> + tst_res(TINFO, "%d %d", shmkey, shmkey1); > > I'm not sure if this message is useful. It is debug message, will remove it. > >> +} >> >> +static void cleanup(void) >> +{ >> + if (shm_id>= 0) >> + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); >> } >> + >> +static struct tst_test test = { >> + .needs_tmpdir = 1, >> + .needs_root = 1, >> + .forks_child = 1, >> + .setup = setup, >> + .cleanup = cleanup, >> + .test = do_test, >> + .tcnt = ARRAY_SIZE(tcases), >> +}; >> diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget03.c b/testcases/kernel/syscalls/ipc/shmget/shmget03.c >> index 96ebf3608..c74fe241d 100644 >> --- a/testcases/kernel/syscalls/ipc/shmget/shmget03.c >> +++ b/testcases/kernel/syscalls/ipc/shmget/shmget03.c >> @@ -1,171 +1,68 @@ >> +// SPDX-License-Identifier: GPL-2.0-or-later > > ... > >> +static int shm_id_arr[SHMMNI] = {-1}; > > The SHMMNI is just default value, it could be adjusted at runtime by > setting /proc/sys/kernel/shmmni > > So we should ideally fix the test to read that value in the test setup > and allocate the array based on the value. Agree. > >> +static void verify_shmget(void) >> { >> - 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(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL >> - | SHM_RW)); >> - >> - 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, "call failed with an " >> - "unexpected error - %d : %s", >> - TEST_ERRNO, strerror(TEST_ERRNO)); >> - break; >> - } >> + TEST(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW)); >> + if (TST_RET != -1) { >> + tst_res(TFAIL, "shmget() returned %li", TST_RET); >> + return; >> } >> - >> - cleanup(); >> - >> - tst_exit(); >> + if (TST_ERR == ENOSPC) >> + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); >> + else >> + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected ENOSPC, bug got"); > > This should be TST_EXP_FAIL() as well. Will do it. > >> } >> >> -/* >> - * setup() - performs all the ONE TIME setup for this test. >> - */ >> -void setup(void) >> +static void setup(void) >> { >> + int res, num; >> >> - 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 */ >> - shmkey = getipckey(); >> - >> - /* >> - * Use a while loop to create the maximum number of memory segments. >> - * If the loop exceeds MAXIDS, then break the test and cleanup. >> - */ >> - while ((shm_id_1 = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | >> - IPC_EXCL | SHM_RW)) != -1) { >> - shm_id_arr[num_shms++] = shm_id_1; >> - if (num_shms == MAXIDS) { >> - tst_brkm(TBROK, cleanup, "The maximum number of shared " >> - "memory ID's has been\n\t reached. Please " >> - "increase the MAXIDS value in the test."); >> - } >> - } >> - >> - /* >> - * If the errno is other than ENOSPC, then something else is wrong. >> - */ >> - if (errno != ENOSPC) { >> - tst_resm(TINFO, "errno = %d : %s", errno, strerror(errno)); >> - tst_brkm(TBROK, cleanup, "Didn't get ENOSPC in test setup"); >> + for (num = 0; num< SHMMNI; num++) { >> + res = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW); >> + if (res != -1) >> + shm_id_arr[num] = res; >> } > > So we attempt to allocate SHMMNI shared memory segemnts and the last > call will fail. > > I guess that we can as well attempt to allocate SHMMNI-1 segemnts and > expect them to all pass. I do not like ignore any failures that may > happen here and cary on with the test. It would be better to TBROK here > instead. > Sounds reansonable. Will do it. >> + tst_res(TINFO, "The maximum number(%d) of memory ID's has been reached", >> + SHMMNI); >> } >> >> -/* >> - * cleanup() - performs all the ONE TIME cleanup for this test at completion >> - * or premature exit. >> - */ >> -void cleanup(void) >> + >> +static void cleanup(void) >> { >> int i; >> >> - /* remove the shared memory resources that were created */ >> - for (i = 0; i< num_shms; i++) { >> - rm_shm(shm_id_arr[i]); >> + for (i = 0; i< SHMMNI; i++) { >> + if (shm_id_arr[i]>= 0) > > This is actually not correct, since there are possibly zeros in the > array (just because it's global variable and only first position is > intialized wiht -1) and we could incorrectly attempt to remove sement > with id 0. > > I guess that the cleanest way how to handle this would be having global > counter for the number of created semgents: > > > static key_t *keys; > static unsigned int max_key; > > setup() > { > ... > keys = SAFE_MALLOC(sizeof(key_t) * shmmni); > ... > > for (;;) { > if (max_key>= shmni) > break; > > > keys[max_key] = shmget(...); > > if (keys[max_key]< 0) > tst_brk(TBROK, ...); > > max_key++; > } > } > > cleanup() > { > key_t key; > > for (key = 0; key< max_key; key++) > SAFE_SHMCTL(keys[key], IPC_RMID, NULL); > } > > > Yes, Will do it in v2. >> + SAFE_SHMCTL(shm_id_arr[i], IPC_RMID, NULL); >> } >> - >> - tst_rmdir(); >> - >> } >> + >> +static struct tst_test test = { >> + .setup = setup, >> + .cleanup = cleanup, >> + .test_all = verify_shmget, >> +}; >> diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget04.c b/testcases/kernel/syscalls/ipc/shmget/shmget04.c >> index 60a263c77..fe611b306 100644 > > ... > >> + tst_res(TINFO, "%s", tc->message); >> + TEST(shmget(shmkey, SHM_SIZE, tc->flag)); >> + if (TST_RET != -1) { >> + tst_res(TFAIL, "shmget() returned %li", TST_RET); >> + return; >> } >> - >> - cleanup(); >> - >> - tst_exit(); >> + if (TST_ERR == EACCES) >> + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); >> + else >> + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected EACCES, bug got"); > > TST_EXP_FAIL() here as well. Will do it. Best Regards Yang Xu > >> } >> >> -/* >> - * setup() - performs all the ONE TIME setup for this test. >> - */ >> -void setup(void) >> +static void setup(void) >> { >> - tst_require_root(); >> - >> - tst_sig(NOFORK, DEF_HANDLER, cleanup); >> + struct passwd *pw; >> >> - TEST_PAUSE; >> - >> - /* Switch to nobody user for correct error code collection */ >> - ltpuser = getpwnam(nobody_uid); >> - if (setuid(ltpuser->pw_uid) == -1) { >> - tst_resm(TINFO, "setuid failed to " >> - "to set the effective uid to %d", ltpuser->pw_uid); >> - perror("setuid"); >> - } >> + pw = SAFE_GETPWNAM("nobody"); >> + SAFE_SETUID(pw->pw_uid); >> + shmkey = GETIPCKEY(); >> >> - /* >> - * 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 */ >> - shmkey = getipckey(); >> - >> - /* create a shared memory segment without read or access permissions */ >> - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL)) == -1) { >> - tst_brkm(TBROK, cleanup, "Failed to create shared memory " >> - "segment in setup"); >> - } >> + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); >> } >> >> -/* >> - * 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 shared memory resource */ >> - rm_shm(shm_id_1); >> - >> - tst_rmdir(); >> - >> + if (shm_id>= 0) >> + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); >> } >> + >> +static struct tst_test test = { >> + .needs_tmpdir = 1, >> + .needs_root = 1, >> + .setup = setup, >> + .cleanup = cleanup, >> + .test = verify_shmget, >> + .tcnt = ARRAY_SIZE(tcases), >> +}; >
diff --git a/include/lapi/shm.h b/include/lapi/shm.h index 61c4e37bf..bb280fc44 100644 --- a/include/lapi/shm.h +++ b/include/lapi/shm.h @@ -6,8 +6,22 @@ #ifndef LAPI_SHM_H__ #define LAPI_SHM_H__ +#include <limits.h> + #ifndef SHM_STAT_ANY # define SHM_STAT_ANY 15 #endif +#ifndef SHMMIN +# define SHMMIN 1 +#endif + +#ifndef SHMMAX +# define SHMMAX (ULONG_MAX - (1UL << 24)) +#endif + +#ifndef SHMMNI +# define SHMMNI 4096 +#endif + #endif /* LAPI_SHM_H__ */ diff --git a/runtest/syscalls b/runtest/syscalls index 63d821e53..2dff25984 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -1402,7 +1402,6 @@ shmdt02 shmdt02 shmget02 shmget02 shmget03 shmget03 shmget04 shmget04 -shmget05 shmget05 sigaction01 sigaction01 sigaction02 sigaction02 diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc index ff0364704..b3bd37923 100644 --- a/runtest/syscalls-ipc +++ b/runtest/syscalls-ipc @@ -67,4 +67,3 @@ shmdt02 shmdt02 shmget02 shmget02 shmget03 shmget03 shmget04 shmget04 -shmget05 shmget05 diff --git a/testcases/kernel/syscalls/ipc/shmget/.gitignore b/testcases/kernel/syscalls/ipc/shmget/.gitignore index 6f08529f8..c57df68f5 100644 --- a/testcases/kernel/syscalls/ipc/shmget/.gitignore +++ b/testcases/kernel/syscalls/ipc/shmget/.gitignore @@ -1,4 +1,3 @@ /shmget02 /shmget03 /shmget04 -/shmget05 diff --git a/testcases/kernel/syscalls/ipc/shmget/Makefile b/testcases/kernel/syscalls/ipc/shmget/Makefile index 26b9f264d..b1201281d 100644 --- a/testcases/kernel/syscalls/ipc/shmget/Makefile +++ b/testcases/kernel/syscalls/ipc/shmget/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/shmget/shmget02.c b/testcases/kernel/syscalls/ipc/shmget/shmget02.c index 4436ca7f8..a57904ce9 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget02.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget02.c @@ -1,184 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* + * Copyright (c) International Business Machines Corp., 2001 + * 03/2001 - Written by Wayne Boyer * - * 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) 2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) */ -/* - * NAME - * shmget02.c - * - * DESCRIPTION - * shmget02 - check for ENOENT, EEXIST and EINVAL errors +/*\ + * [Description] * - * ALGORITHM - * create a shared memory segment with read & write permissions - * loop if that option was specified - * call shmget() using five different invalid cases - * check the errno value - * issue a PASS message if we get ENOENT, EEXIST or EINVAL - * otherwise, the tests fails - * issue a FAIL message - * call cleanup + * Test for ENOENT, EEXIST, EINVAL, EACCES errors. * - * USAGE: <for command-line> - * shmget02 [-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 - * - * 06/03/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) - * - Fix concurrency issue. The second key used for this test could - * conflict with the key from another task. - * - * RESTRICTIONS - * none + * 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 + * greater than the size of that segment. + * EACCES - The user does not have permission to access the shared memory segment. */ - -#include "ipcshm.h" - -char *TCID = "shmget02"; -int TST_TOTAL = 4; - -int shm_id_1 = -1; -int shm_nonexisting_key = -1; -key_t shmkey2; - -struct test_case_t { - int *skey; - int size; +#include <errno.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <stdlib.h> +#include <pwd.h> +#include <sys/shm.h> +#include "tst_safe_sysv_ipc.h" +#include "tst_test.h" +#include "libnewipc.h" +#include "lapi/shm.h" + +static int shm_id = -1; +static key_t shmkey, shmkey1; +static struct passwd *pw; + +static struct tcase { + int *shmkey; + size_t size; int flags; - int error; -} TC[] = { - /* EINVAL - size is 0 */ - { - &shmkey2, 0, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, - /* EINVAL - size is negative */ -// {&shmkey2, -1, IPC_CREAT | IPC_EXCL | SHM_RW, EINVAL}, - /* EINVAL - size is larger than created segment */ - { - &shmkey, SHM_SIZE * 2, SHM_RW, EINVAL}, - /* EEXIST - the segment exists and IPC_CREAT | IPC_EXCL is given */ - { - &shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW, EEXIST}, - /* ENOENT - no segment exists for the key and IPC_CREAT is not given */ - /* use shm_id_2 (-1) as the key */ - { - &shm_nonexisting_key, SHM_SIZE, SHM_RW, ENOENT} + /*1: nobody expected 0: root expected */ + int exp_user; + int exp_err; +} tcases[] = { + {&shmkey1, SHM_SIZE, IPC_EXCL, 0, ENOENT}, + {&shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL, 0, EEXIST}, + {&shmkey1, SHMMIN - 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, + {&shmkey1, SHMMAX + 1, IPC_CREAT | IPC_EXCL, 0, EINVAL}, + {&shmkey, SHM_SIZE * 2, IPC_EXCL, 0, EINVAL}, + {&shmkey, SHM_SIZE, SHM_RD, 1, EACCES}, }; -int main(int ac, char **av) +static void verify_shmget(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; - - /* loop through the test cases */ - for (i = 0; i < TST_TOTAL; i++) { - /* - * Look for a failure ... - */ - - TEST(shmget(*(TC[i].skey), TC[i].size, TC[i].flags)); - - if (TEST_RETURN != -1) { - tst_resm(TFAIL, "call succeeded unexpectedly"); - continue; - } - - if (TEST_ERRNO == TC[i].error) { - tst_resm(TPASS, "expected failure - errno = " - "%d : %s", TEST_ERRNO, - strerror(TEST_ERRNO)); - } else { - tst_resm(TFAIL, "call failed with an " - "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - } - } + TEST(shmget(*tc->shmkey, tc->size, tc->flags)); + if (TST_RET != -1) { + tst_res(TFAIL, "shmget() returned %li", TST_RET); + return; } - cleanup(); + if (TST_ERR == tc->exp_err) { + tst_res(TPASS | TTERRNO, "shmget(%i, %lu, %i)", + *tc->shmkey, tc->size, tc->flags); + return; + } - tst_exit(); + tst_res(TFAIL | TTERRNO, "shmget(%i, %lu, %i) expected %s", + *tc->shmkey, tc->size, tc->flags, tst_strerrno(tc->exp_err)); } -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) +static void do_test(unsigned int n) { + struct tcase *tc = &tcases[n]; + pid_t pid; - 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 */ - shmkey = getipckey(); - - /* Get an new IPC resource key. */ - shmkey2 = getipckey(); - - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL | - SHM_RW)) == -1) { - tst_brkm(TBROK, cleanup, "couldn't create shared memory " - "segment in setup()"); + if (tc->exp_user == 0) { + verify_shmget(tc); + return; } - /* Make sure shm_nonexisting_key is a nonexisting key */ - while (1) { - while (-1 != shmget(shm_nonexisting_key, 1, SHM_RD)) { - shm_nonexisting_key--; - } - if (errno == ENOENT) - break; + pid = SAFE_FORK(); + if (pid == 0) { + SAFE_SETUID(pw->pw_uid); + verify_shmget(tc); + exit(0); } + tst_reap_children(); } -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) +static void setup(void) { - /* if it exists, remove the shared memory resource */ - rm_shm(shm_id_1); + shmkey = GETIPCKEY(); + shmkey1 = GETIPCKEY(); - tst_rmdir(); + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); + pw = SAFE_GETPWNAM("nobody"); + tst_res(TINFO, "%d %d", shmkey, shmkey1); +} +static void cleanup(void) +{ + if (shm_id >= 0) + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .needs_root = 1, + .forks_child = 1, + .setup = setup, + .cleanup = cleanup, + .test = do_test, + .tcnt = ARRAY_SIZE(tcases), +}; diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget03.c b/testcases/kernel/syscalls/ipc/shmget/shmget03.c index 96ebf3608..c74fe241d 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget03.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget03.c @@ -1,171 +1,68 @@ +// 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 + * 03/2001 - Written by Wayne Boyer */ -/* - * NAME - * shmget03.c +/*\ + * [Description] * - * DESCRIPTION - * shmget03 - test for ENOSPC error + * Test for ENOSPC error. * - * ALGORITHM - * create shared memory segments in a loop until reaching the system limit - * loop if that option was specified - * attempt to create yet another shared memory segment - * check the errno value - * issue a PASS message if we get ENOSPC - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * shmget03 [-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 "ipcshm.h" - -char *TCID = "shmget03"; -int TST_TOTAL = 1; - -/* - * The MAXIDS value is somewhat arbitrary and may need to be increased - * depending on the system being tested. + * ENOSPC - All possible shared memory IDs have been taken (SHMMNI). */ -#define MAXIDS 8192 - -int shm_id_1 = -1; -int num_shms = 0; - -int shm_id_arr[MAXIDS]; - -int main(int ac, char **av) +#include <errno.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <stdlib.h> +#include <pwd.h> +#include <sys/shm.h> +#include "tst_safe_sysv_ipc.h" +#include "tst_test.h" +#include "libnewipc.h" +#include "lapi/shm.h" + +static int shm_id_arr[SHMMNI] = {-1}; + +static void verify_shmget(void) { - 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(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL - | SHM_RW)); - - 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, "call failed with an " - "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } + TEST(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW)); + if (TST_RET != -1) { + tst_res(TFAIL, "shmget() returned %li", TST_RET); + return; } - - cleanup(); - - tst_exit(); + if (TST_ERR == ENOSPC) + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); + else + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected ENOSPC, bug got"); } -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) +static void setup(void) { + int res, num; - 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 */ - shmkey = getipckey(); - - /* - * Use a while loop to create the maximum number of memory segments. - * If the loop exceeds MAXIDS, then break the test and cleanup. - */ - while ((shm_id_1 = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | - IPC_EXCL | SHM_RW)) != -1) { - shm_id_arr[num_shms++] = shm_id_1; - if (num_shms == MAXIDS) { - tst_brkm(TBROK, cleanup, "The maximum number of shared " - "memory ID's has been\n\t reached. Please " - "increase the MAXIDS value in the test."); - } - } - - /* - * If the errno is other than ENOSPC, then something else is wrong. - */ - if (errno != ENOSPC) { - tst_resm(TINFO, "errno = %d : %s", errno, strerror(errno)); - tst_brkm(TBROK, cleanup, "Didn't get ENOSPC in test setup"); + for (num = 0; num < SHMMNI; num++) { + res = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW); + if (res != -1) + shm_id_arr[num] = res; } + tst_res(TINFO, "The maximum number(%d) of memory ID's has been reached", + SHMMNI); } -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) + +static void cleanup(void) { int i; - /* remove the shared memory resources that were created */ - for (i = 0; i < num_shms; i++) { - rm_shm(shm_id_arr[i]); + for (i = 0; i < SHMMNI; i++) { + if (shm_id_arr[i] >= 0) + SAFE_SHMCTL(shm_id_arr[i], IPC_RMID, NULL); } - - tst_rmdir(); - } + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = verify_shmget, +}; diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget04.c b/testcases/kernel/syscalls/ipc/shmget/shmget04.c index 60a263c77..fe611b306 100644 --- a/testcases/kernel/syscalls/ipc/shmget/shmget04.c +++ b/testcases/kernel/syscalls/ipc/shmget/shmget04.c @@ -1,153 +1,78 @@ +// 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 + * 03/2001 - Written by Wayne Boyer */ -/* - * NAME - * shmget04.c +/*\ + * [Description] * - * DESCRIPTION - * shmget04 - test for EACCES error + * Test for EACCES error. * - * ALGORITHM - * create a shared memory segment without read or write permissions - * loop if that option was specified - * call shmget() with SHM_RW flag using TEST() macro - * check the errno value - * issue a PASS message if we get EACCES - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * - * USAGE: <for command-line> - * shmget04 [-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 + * Create a shared memory segment without read or write permissions under + * unpriviledged user and call shmget() with SHM_RD/SHM_WR/SHM_RW flag to + * trigger EACCES error. */ +#include <errno.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <stdlib.h> #include <pwd.h> -#include "ipcshm.h" - -char *TCID = "shmget04"; -int TST_TOTAL = 1; - -char nobody_uid[] = "nobody"; -struct passwd *ltpuser; - -int shm_id_1 = -1; - -int main(int ac, char **av) +#include <sys/shm.h> +#include "tst_safe_sysv_ipc.h" +#include "tst_test.h" +#include "libnewipc.h" +#include "lapi/shm.h" + +static int shm_id = -1; +static key_t shmkey; +static struct tcase { + char *message; + int flag; +} tcases[] = { + {"Testing SHM_RD flag", SHM_RD}, + {"Testing SHM_WR flag", SHM_WR}, + {"Testing SHM_RW flag", SHM_RW}, +}; + +static void verify_shmget(unsigned int n) { - 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 - */ + struct tcase *tc = &tcases[n]; - TEST(shmget(shmkey, SHM_SIZE, SHM_RW)); - - if (TEST_RETURN != -1) { - tst_resm(TFAIL, "call succeeded when error expected"); - continue; - } - - switch (TEST_ERRNO) { - case EACCES: - tst_resm(TPASS, "expected failure - errno = " - "%d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); - break; - default: - tst_resm(TFAIL, "call failed with an " - "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } + tst_res(TINFO, "%s", tc->message); + TEST(shmget(shmkey, SHM_SIZE, tc->flag)); + if (TST_RET != -1) { + tst_res(TFAIL, "shmget() returned %li", TST_RET); + return; } - - cleanup(); - - tst_exit(); + if (TST_ERR == EACCES) + tst_res(TPASS | TTERRNO, "shmget() failed as expected"); + else + tst_res(TFAIL | TTERRNO, "shmget() failed unexpectedly, expected EACCES, bug got"); } -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) +static void setup(void) { - tst_require_root(); - - tst_sig(NOFORK, DEF_HANDLER, cleanup); + struct passwd *pw; - TEST_PAUSE; - - /* Switch to nobody user for correct error code collection */ - ltpuser = getpwnam(nobody_uid); - if (setuid(ltpuser->pw_uid) == -1) { - tst_resm(TINFO, "setuid failed to " - "to set the effective uid to %d", ltpuser->pw_uid); - perror("setuid"); - } + pw = SAFE_GETPWNAM("nobody"); + SAFE_SETUID(pw->pw_uid); + shmkey = GETIPCKEY(); - /* - * 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 */ - shmkey = getipckey(); - - /* create a shared memory segment without read or access permissions */ - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL)) == -1) { - tst_brkm(TBROK, cleanup, "Failed to create shared memory " - "segment in setup"); - } + shm_id = SAFE_SHMGET(shmkey, SHM_SIZE, IPC_CREAT | IPC_EXCL); } -/* - * 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 shared memory resource */ - rm_shm(shm_id_1); - - tst_rmdir(); - + if (shm_id >= 0) + SAFE_SHMCTL(shm_id, IPC_RMID, NULL); } + +static struct tst_test test = { + .needs_tmpdir = 1, + .needs_root = 1, + .setup = setup, + .cleanup = cleanup, + .test = verify_shmget, + .tcnt = ARRAY_SIZE(tcases), +}; diff --git a/testcases/kernel/syscalls/ipc/shmget/shmget05.c b/testcases/kernel/syscalls/ipc/shmget/shmget05.c deleted file mode 100644 index de9544591..000000000 --- a/testcases/kernel/syscalls/ipc/shmget/shmget05.c +++ /dev/null @@ -1,185 +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 - * shmget05.c - * - * DESCRIPTION - * shmget05 - test for EACCES error - * - * ALGORITHM - * create a shared memory segment with root only read & write permissions - * fork a child process - * if child - * set the ID of the child process to that of "nobody" - * loop if that option was specified - * call shmget() using the TEST() macro - * check the errno value - * issue a PASS message if we get EACCES - * otherwise, the tests fails - * issue a FAIL message - * call cleanup - * if parent - * wait for child to exit - * remove the shared memory segment - * - * USAGE: <for command-line> - * shmget05 [-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 - * test must be run at root - */ - -#include "ipcshm.h" -#include <sys/types.h> -#include <sys/wait.h> -#include "safe_macros.h" - -char *TCID = "shmget05"; -int TST_TOTAL = 1; - -int shm_id_1 = -1; - -uid_t ltp_uid; -char *ltp_user = "nobody"; - -int main(int ac, char **av) -{ - int pid; - void do_child(void); - - tst_parse_opts(ac, av, NULL, NULL); - - setup(); /* global setup */ - - if ((pid = FORK_OR_VFORK()) == -1) { - tst_brkm(TBROK, cleanup, "could not fork"); - } - - if (pid == 0) { /* child */ - /* set the user ID of the child to the non root user */ - if (setuid(ltp_uid) == -1) { - tst_resm(TBROK, "setuid() failed"); - exit(1); - } - - do_child(); - - cleanup(); - - } else { /* parent */ - /* wait for the child to return */ - SAFE_WAITPID(cleanup, pid, NULL, 0); - - /* if it exists, remove the shared memory resource */ - rm_shm(shm_id_1); - - tst_rmdir(); - } - tst_exit(); -} - -/* - * do_child - make the TEST call as the child process - */ -void do_child(void) -{ - int lc; - - /* 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; - - /* - * Look for a failure ... - */ - - TEST(shmget(shmkey, SHM_SIZE, SHM_RW)); - - if (TEST_RETURN != -1) { - tst_resm(TFAIL, "call succeeded when error expected"); - continue; - } - - switch (TEST_ERRNO) { - case EACCES: - tst_resm(TPASS, "expected failure - errno = " - "%d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); - break; - default: - tst_resm(TFAIL, "call failed with an " - "unexpected error - %d : %s", - TEST_ERRNO, strerror(TEST_ERRNO)); - break; - } - } -} - -/* - * setup() - performs all the ONE TIME setup for this test. - */ -void setup(void) -{ - tst_require_root(); - - tst_sig(FORK, 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 */ - shmkey = getipckey(); - - /* create a shared memory segment with read and write permissions */ - if ((shm_id_1 = shmget(shmkey, SHM_SIZE, - SHM_RW | IPC_CREAT | IPC_EXCL)) == -1) { - tst_brkm(TBROK, cleanup, "Failed to create shared memory " - "segment in setup"); - } - - /* get the userid for a non root user */ - ltp_uid = getuserid(ltp_user); -} - -/* - * cleanup() - performs all the ONE TIME cleanup for this test at completion - * or premature exit. - */ -void cleanup(void) -{ - -}
1) merge shmget05.c into shmget02.c 2) Use SHMMIN -1 and SHMMAX + 1 to trigger EINVAL error 3) Use SHM_RD, SHM_WR, SHM_RW to trigger EACCES error under unpriviledged user Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com> --- include/lapi/shm.h | 14 + runtest/syscalls | 1 - runtest/syscalls-ipc | 1 - .../kernel/syscalls/ipc/shmget/.gitignore | 1 - testcases/kernel/syscalls/ipc/shmget/Makefile | 4 +- .../kernel/syscalls/ipc/shmget/shmget02.c | 243 +++++++----------- .../kernel/syscalls/ipc/shmget/shmget03.c | 199 ++++---------- .../kernel/syscalls/ipc/shmget/shmget04.c | 193 +++++--------- .../kernel/syscalls/ipc/shmget/shmget05.c | 185 ------------- 9 files changed, 209 insertions(+), 632 deletions(-) delete mode 100644 testcases/kernel/syscalls/ipc/shmget/shmget05.c