1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2004 4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2004-2020 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * DESCRIPTION 9f08c3bdfSopenharmony_ci * hugeshmctl02 - check for EACCES, EFAULT and EINVAL errors 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * ALGORITHM 12f08c3bdfSopenharmony_ci * create a large shared memory segment without read or write permissions 13f08c3bdfSopenharmony_ci * create a large shared memory segment with read & write permissions 14f08c3bdfSopenharmony_ci * loop if that option was specified 15f08c3bdfSopenharmony_ci * call shmctl() using five different invalid cases 16f08c3bdfSopenharmony_ci * check the errno value 17f08c3bdfSopenharmony_ci * issue a PASS message if we get EACCES, EFAULT or EINVAL 18f08c3bdfSopenharmony_ci * otherwise, the tests fails 19f08c3bdfSopenharmony_ci * issue a FAIL message 20f08c3bdfSopenharmony_ci * call cleanup 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * HISTORY 23f08c3bdfSopenharmony_ci * 03/2001 - Written by Wayne Boyer 24f08c3bdfSopenharmony_ci * 04/2004 - Updated by Robbie Williamson 25f08c3bdfSopenharmony_ci */ 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#include <pwd.h> 28f08c3bdfSopenharmony_ci#include <limits.h> 29f08c3bdfSopenharmony_ci#include "hugetlb.h" 30f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic size_t shm_size; 33f08c3bdfSopenharmony_cistatic int shm_id_1 = -1; 34f08c3bdfSopenharmony_cistatic int shm_id_2 = -1; 35f08c3bdfSopenharmony_cistatic int shm_id_3 = -1; 36f08c3bdfSopenharmony_cistatic struct shmid_ds buf; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_cistatic struct tcase { 39f08c3bdfSopenharmony_ci int *shmid; 40f08c3bdfSopenharmony_ci int cmd; 41f08c3bdfSopenharmony_ci struct shmid_ds *sbuf; 42f08c3bdfSopenharmony_ci int error; 43f08c3bdfSopenharmony_ci} tcases[] = { 44f08c3bdfSopenharmony_ci /* EFAULT - IPC_SET & buf isn't valid */ 45f08c3bdfSopenharmony_ci {&shm_id_2, IPC_SET, (struct shmid_ds *)-1, EFAULT}, 46f08c3bdfSopenharmony_ci /* EFAULT - IPC_STAT & buf isn't valid */ 47f08c3bdfSopenharmony_ci {&shm_id_2, IPC_STAT, (struct shmid_ds *)-1, EFAULT}, 48f08c3bdfSopenharmony_ci /* EINVAL - the shmid is not valid */ 49f08c3bdfSopenharmony_ci {&shm_id_3, IPC_STAT, &buf, EINVAL}, 50f08c3bdfSopenharmony_ci /* EINVAL - the command is not valid */ 51f08c3bdfSopenharmony_ci {&shm_id_2, -1, &buf, EINVAL}, 52f08c3bdfSopenharmony_ci}; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistatic int libc_shmctl(int shmid, int cmd, void *buf) 55f08c3bdfSopenharmony_ci{ 56f08c3bdfSopenharmony_ci return shmctl(shmid, cmd, buf); 57f08c3bdfSopenharmony_ci} 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_cistatic int sys_shmctl(int shmid, int cmd, void *buf) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci return tst_syscall(__NR_shmctl, shmid, cmd, buf); 62f08c3bdfSopenharmony_ci} 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_cistatic struct test_variants 65f08c3bdfSopenharmony_ci{ 66f08c3bdfSopenharmony_ci int (*shmctl)(int shmid, int cmd, void *buf); 67f08c3bdfSopenharmony_ci char *desc; 68f08c3bdfSopenharmony_ci} variants[] = { 69f08c3bdfSopenharmony_ci { .shmctl = libc_shmctl, .desc = "libc shmctl()"}, 70f08c3bdfSopenharmony_ci#if (__NR_shmctl != __LTP__NR_INVALID_SYSCALL) 71f08c3bdfSopenharmony_ci { .shmctl = sys_shmctl, .desc = "__NR_shmctl syscall"}, 72f08c3bdfSopenharmony_ci#endif 73f08c3bdfSopenharmony_ci}; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_cistatic void test_hugeshmctl(unsigned int i) 76f08c3bdfSopenharmony_ci{ 77f08c3bdfSopenharmony_ci struct test_variants *tv = &variants[tst_variant]; 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci if (tcases[i].error == EFAULT && tv->shmctl == libc_shmctl) { 80f08c3bdfSopenharmony_ci tst_res(TCONF, "EFAULT is skipped for libc variant"); 81f08c3bdfSopenharmony_ci return; 82f08c3bdfSopenharmony_ci } 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci TEST(tv->shmctl(*(tcases[i].shmid), tcases[i].cmd, tcases[i].sbuf)); 85f08c3bdfSopenharmony_ci if (TST_RET != -1) { 86f08c3bdfSopenharmony_ci tst_res(TFAIL, "shmctl succeeded unexpectedly"); 87f08c3bdfSopenharmony_ci return; 88f08c3bdfSopenharmony_ci } 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci if (TST_ERR == tcases[i].error) { 91f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "shmctl failed as expected"); 92f08c3bdfSopenharmony_ci return; 93f08c3bdfSopenharmony_ci } 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 96f08c3bdfSopenharmony_ci "shmctl failed unexpectedly - expect errno = %d, got", 97f08c3bdfSopenharmony_ci tcases[i].error); 98f08c3bdfSopenharmony_ci} 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_cistatic void setup(void) 101f08c3bdfSopenharmony_ci{ 102f08c3bdfSopenharmony_ci struct test_variants *tv = &variants[tst_variant]; 103f08c3bdfSopenharmony_ci long hpage_size; 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", tv->desc); 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci if (tst_hugepages == 0) 108f08c3bdfSopenharmony_ci tst_brk(TCONF, "No enough hugepages for testing."); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci shm_size = hpage_size * (tst_hugepages / 2); 113f08c3bdfSopenharmony_ci update_shm_size(&shm_size); 114f08c3bdfSopenharmony_ci shmkey = getipckey(); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci /* create a shared memory segment without read or write permissions */ 117f08c3bdfSopenharmony_ci shm_id_1 = shmget(shmkey, shm_size, SHM_HUGETLB | IPC_CREAT | IPC_EXCL); 118f08c3bdfSopenharmony_ci if (shm_id_1 == -1) 119f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmget #1"); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci /* create a shared memory segment with read and write permissions */ 122f08c3bdfSopenharmony_ci shm_id_2 = shmget(shmkey + 1, shm_size, 123f08c3bdfSopenharmony_ci SHM_HUGETLB | IPC_CREAT | IPC_EXCL | SHM_RW); 124f08c3bdfSopenharmony_ci if (shm_id_2 == -1) 125f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmget #2"); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic void cleanup(void) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci rm_shm(shm_id_1); 131f08c3bdfSopenharmony_ci rm_shm(shm_id_2); 132f08c3bdfSopenharmony_ci} 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_cistatic struct tst_test test = { 135f08c3bdfSopenharmony_ci .test = test_hugeshmctl, 136f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 137f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 138f08c3bdfSopenharmony_ci .needs_root = 1, 139f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 140f08c3bdfSopenharmony_ci .options = (struct tst_option[]) { 141f08c3bdfSopenharmony_ci {"s:", &nr_opt, "Set the number of the been allocated hugepages"}, 142f08c3bdfSopenharmony_ci {} 143f08c3bdfSopenharmony_ci }, 144f08c3bdfSopenharmony_ci .setup = setup, 145f08c3bdfSopenharmony_ci .cleanup = cleanup, 146f08c3bdfSopenharmony_ci .hugepages = {128, TST_REQUEST}, 147f08c3bdfSopenharmony_ci}; 148