1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 03/2001 - Written by Wayne Boyer 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Copyright (c) 2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com) 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * Copyright (C) 2020 Cyril Hrubis <chrubis@suse.cz> 9f08c3bdfSopenharmony_ci */ 10f08c3bdfSopenharmony_ci 11f08c3bdfSopenharmony_ci/*\ 12f08c3bdfSopenharmony_ci * [Description] 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * Test for EACCES, EFAULT and EINVAL errors. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * * EACCES - segment has no read or write permissions 17f08c3bdfSopenharmony_ci * * EFAULT - IPC_SET & buf isn't valid 18f08c3bdfSopenharmony_ci * * EFAULT - IPC_STAT & buf isn't valid 19f08c3bdfSopenharmony_ci * * EINVAL - the command is not valid 20f08c3bdfSopenharmony_ci * * EINVAL - the shmid is not valid 21f08c3bdfSopenharmony_ci * * EINVAL - the shmid belongs to removed shm 22f08c3bdfSopenharmony_ci * 23f08c3bdfSopenharmony_ci * * EACCES - attempt to stat root-owned shm 24f08c3bdfSopenharmony_ci * * EPERM - attempt to delete root-owned shm 25f08c3bdfSopenharmony_ci * * EPERM - attempt to change root-owned shm 26f08c3bdfSopenharmony_ci * * EPERM - attempt to lock root-owned shm 27f08c3bdfSopenharmony_ci * * EPERM - attempt to unlock root-owned shm 28f08c3bdfSopenharmony_ci */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include <pwd.h> 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include "tst_test.h" 33f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h" 34f08c3bdfSopenharmony_ci#include "libnewipc.h" 35f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci#define SHM_SIZE 2048 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic int shm_id1 = -1; 40f08c3bdfSopenharmony_cistatic int shm_id2 = -1; 41f08c3bdfSopenharmony_cistatic int shm_id3 = -1; 42f08c3bdfSopenharmony_cistatic int shm_bad = -1; 43f08c3bdfSopenharmony_cistatic int shm_rem; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic struct shmid_ds buf; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic int libc_shmctl(int shmid, int cmd, void *buf) 48f08c3bdfSopenharmony_ci{ 49f08c3bdfSopenharmony_ci return shmctl(shmid, cmd, buf); 50f08c3bdfSopenharmony_ci} 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic int sys_shmctl(int shmid, int cmd, void *buf) 53f08c3bdfSopenharmony_ci{ 54f08c3bdfSopenharmony_ci return tst_syscall(__NR_shmctl, shmid, cmd, buf); 55f08c3bdfSopenharmony_ci} 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic struct tcase { 58f08c3bdfSopenharmony_ci int *shm_id; 59f08c3bdfSopenharmony_ci int cmd; 60f08c3bdfSopenharmony_ci struct shmid_ds *buf; 61f08c3bdfSopenharmony_ci int error; 62f08c3bdfSopenharmony_ci} tc[] = { 63f08c3bdfSopenharmony_ci {&shm_id1, IPC_STAT, &buf, EACCES}, 64f08c3bdfSopenharmony_ci {&shm_id2, IPC_SET, (struct shmid_ds *)-1, EFAULT}, 65f08c3bdfSopenharmony_ci {&shm_id2, IPC_STAT, (struct shmid_ds *)-1, EFAULT}, 66f08c3bdfSopenharmony_ci {&shm_id2, -1, &buf, EINVAL}, 67f08c3bdfSopenharmony_ci {&shm_bad, IPC_STAT, &buf, EINVAL}, 68f08c3bdfSopenharmony_ci {&shm_rem, IPC_STAT, &buf, EINVAL}, 69f08c3bdfSopenharmony_ci /* Operations on root-owned shm */ 70f08c3bdfSopenharmony_ci {&shm_id3, IPC_STAT, &buf, EACCES}, 71f08c3bdfSopenharmony_ci {&shm_id3, IPC_RMID, NULL, EPERM}, 72f08c3bdfSopenharmony_ci {&shm_id3, IPC_SET, &buf, EPERM}, 73f08c3bdfSopenharmony_ci {&shm_id3, SHM_LOCK, &buf, EPERM}, 74f08c3bdfSopenharmony_ci {&shm_id3, SHM_UNLOCK, &buf, EPERM} 75f08c3bdfSopenharmony_ci}; 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic struct test_variants 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci int (*shmctl)(int shmid, int cmd, void *buf); 80f08c3bdfSopenharmony_ci char *desc; 81f08c3bdfSopenharmony_ci} variants[] = { 82f08c3bdfSopenharmony_ci { .shmctl = libc_shmctl, .desc = "libc shmctl()"}, 83f08c3bdfSopenharmony_ci#if (__NR_shmctl != __LTP__NR_INVALID_SYSCALL) 84f08c3bdfSopenharmony_ci { .shmctl = sys_shmctl, .desc = "__NR_shmctl syscall"}, 85f08c3bdfSopenharmony_ci#endif 86f08c3bdfSopenharmony_ci}; 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_cistatic void verify_shmctl(unsigned int i) 89f08c3bdfSopenharmony_ci{ 90f08c3bdfSopenharmony_ci struct test_variants *tv = &variants[tst_variant]; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci if (tc[i].error == EFAULT && tv->shmctl == libc_shmctl) { 93f08c3bdfSopenharmony_ci tst_res(TCONF, "EFAULT is skipped for libc variant"); 94f08c3bdfSopenharmony_ci return; 95f08c3bdfSopenharmony_ci } 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci TST_EXP_FAIL(tv->shmctl(*(tc[i].shm_id), tc[i].cmd, tc[i].buf), 98f08c3bdfSopenharmony_ci tc[i].error, "shmctl(%i, %i, %p)", *(tc[i].shm_id), tc[i].cmd, tc[i].buf); 99f08c3bdfSopenharmony_ci} 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_cistatic void setup(void) 102f08c3bdfSopenharmony_ci{ 103f08c3bdfSopenharmony_ci struct test_variants *tv = &variants[tst_variant]; 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci key_t shmkey1, shmkey2; 106f08c3bdfSopenharmony_ci struct passwd *ltpuser; 107f08c3bdfSopenharmony_ci int tmp; 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci tst_res(TINFO, "Testing variant: %s", tv->desc); 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci shm_id3 = SAFE_SHMGET(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | SHM_RW); 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM("nobody"); 114f08c3bdfSopenharmony_ci SAFE_SETEUID(ltpuser->pw_uid); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci shmkey1 = GETIPCKEY(); 117f08c3bdfSopenharmony_ci shmkey2 = GETIPCKEY(); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci shm_id1 = SAFE_SHMGET(shmkey1, SHM_SIZE, IPC_CREAT | IPC_EXCL); 120f08c3bdfSopenharmony_ci shm_id2 = SAFE_SHMGET(shmkey2, SHM_SIZE, IPC_CREAT | IPC_EXCL | SHM_RW); 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci tmp = shm_rem = SAFE_SHMGET(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | SHM_RW); 123f08c3bdfSopenharmony_ci SAFE_SHMCTL(tmp, IPC_RMID, NULL); 124f08c3bdfSopenharmony_ci} 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_cistatic void cleanup(void) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci if (shm_id1 >= 0) 129f08c3bdfSopenharmony_ci SAFE_SHMCTL(shm_id1, IPC_RMID, NULL); 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci if (shm_id2 >= 0) 132f08c3bdfSopenharmony_ci SAFE_SHMCTL(shm_id2, IPC_RMID, NULL); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci if (shm_id3 >= 0) { 135f08c3bdfSopenharmony_ci SAFE_SETEUID(0); 136f08c3bdfSopenharmony_ci SAFE_SHMCTL(shm_id3, IPC_RMID, NULL); 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci} 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_cistatic struct tst_test test = { 141f08c3bdfSopenharmony_ci .setup = setup, 142f08c3bdfSopenharmony_ci .cleanup = cleanup, 143f08c3bdfSopenharmony_ci .test = verify_shmctl, 144f08c3bdfSopenharmony_ci .test_variants = ARRAY_SIZE(variants), 145f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tc), 146f08c3bdfSopenharmony_ci .needs_root = 1, 147f08c3bdfSopenharmony_ci}; 148