1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2020 Cyril Hrubis <chrubis@suse.cz> 4 */ 5 6/*\ 7 * [Description] 8 * 9 * Test for a SHM_SET. 10 * 11 * The test clears the group and others bits from the shm_perm.mode and checks 12 * the result as well as if the ctime was updated correctly. 13 */ 14 15#define _GNU_SOURCE 16#include <stdio.h> 17#include "tst_test.h" 18#include "tst_safe_sysv_ipc.h" 19#include "libnewipc.h" 20 21#define SHM_SIZE 2048 22 23static int shm_id = -1; 24 25static int test_ipc_set(struct shmid_ds *ds) 26{ 27 TEST(shmctl(shm_id, IPC_SET, ds)); 28 29 if (TST_RET != 0) { 30 tst_res(TFAIL, "shmctl(%i, IPC_SET, ...)", shm_id); 31 return 1; 32 } 33 34 tst_res(TPASS, "shmctl(%i, IPC_SET, {shm_perm.mode=%04o})", 35 shm_id, ds->shm_perm.mode); 36 return 0; 37} 38 39static void check_mode(struct shmid_ds *ds, short exp_mode) 40{ 41 if (ds->shm_perm.mode == exp_mode) { 42 tst_res(TPASS, "shm_perm.mode=%04o", exp_mode); 43 return; 44 } 45 46 tst_res(TFAIL, "shm_perm.mode=%04o, expected %i", 47 ds->shm_perm.mode, exp_mode); 48} 49 50static void verify_shmset(void) 51{ 52 struct shmid_ds ds; 53 unsigned short old_mode; 54 time_t old_ctime; 55 56 SAFE_SHMCTL(shm_id, IPC_STAT, &ds); 57 58 old_mode = ds.shm_perm.mode; 59 old_ctime = ds.shm_ctime; 60 61 check_mode(&ds, 0666); 62 63 sleep(1); 64 65 ds.shm_perm.mode &= ~0066; 66 67 if (test_ipc_set(&ds)) 68 return; 69 70 memset(&ds, 0, sizeof(ds)); 71 SAFE_SHMCTL(shm_id, IPC_STAT, &ds); 72 check_mode(&ds, old_mode & ~0066); 73 74 if (ds.shm_ctime <= old_ctime || ds.shm_ctime > old_ctime + 10) { 75 tst_res(TFAIL, "shm_ctime not updated old %li new %li", 76 (long)old_ctime, (long)ds.shm_ctime); 77 } else { 78 tst_res(TPASS, "shm_ctime updated correctly diff=%li", 79 (long)(ds.shm_ctime - old_ctime)); 80 } 81 82 ds.shm_perm.mode = old_mode; 83 if (test_ipc_set(&ds)) 84 return; 85 86 memset(&ds, 0, sizeof(ds)); 87 SAFE_SHMCTL(shm_id, IPC_STAT, &ds); 88 check_mode(&ds, old_mode & MODE_MASK); 89} 90 91static void setup(void) 92{ 93 shm_id = SAFE_SHMGET(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666); 94} 95 96static void cleanup(void) 97{ 98 if (shm_id >= 0) 99 SAFE_SHMCTL(shm_id, IPC_RMID, NULL); 100} 101 102static struct tst_test test = { 103 .setup = setup, 104 .cleanup = cleanup, 105 .test_all = verify_shmset, 106}; 107