1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved. 4f08c3bdfSopenharmony_ci * Author: Feiyu Zhu <zhufy.jy@cn.fujitsu.com> 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Call msgctl() with MSG_INFO flag and check that: 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * * The returned index points to a valid MSG by calling MSG_STAT_ANY 12f08c3bdfSopenharmony_ci * * Also count that valid indexes < returned max index sums up to used_ids 13f08c3bdfSopenharmony_ci * * And the data are consistent with /proc/sysvipc/msg 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * There is a possible race between the call to the msgctl() and read from the 16f08c3bdfSopenharmony_ci * proc file so this test cannot be run in parallel with any IPC testcases that 17f08c3bdfSopenharmony_ci * adds or removes MSG queues. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * Note what we create a MSG segment in the test setup and send msg to make sure 20f08c3bdfSopenharmony_ci * that there is at least one during the testrun. 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * Also note that for MSG_INFO the members of the msginfo structure have 23f08c3bdfSopenharmony_ci * completely different meaning than their names seems to suggest. 24f08c3bdfSopenharmony_ci */ 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#include <stdio.h> 27f08c3bdfSopenharmony_ci#include <pwd.h> 28f08c3bdfSopenharmony_ci#include "tst_test.h" 29f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h" 30f08c3bdfSopenharmony_ci#include "libnewipc.h" 31f08c3bdfSopenharmony_ci#include "lapi/msg.h" 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic int msg_id = -1; 34f08c3bdfSopenharmony_cistatic struct passwd *ltpuser; 35f08c3bdfSopenharmony_cistatic uid_t nobody_uid, root_uid; 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cistatic struct tcases { 38f08c3bdfSopenharmony_ci uid_t *uid; 39f08c3bdfSopenharmony_ci char *desc; 40f08c3bdfSopenharmony_ci} tests[] = { 41f08c3bdfSopenharmony_ci {&nobody_uid, "with nobody user"}, 42f08c3bdfSopenharmony_ci {&root_uid, "with root user"} 43f08c3bdfSopenharmony_ci}; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void parse_proc_sysvipc(struct msginfo *info) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci FILE *f = fopen("/proc/sysvipc/msg", "r"); 48f08c3bdfSopenharmony_ci int queue_cnt = 0; 49f08c3bdfSopenharmony_ci int msg_cnt = 0; 50f08c3bdfSopenharmony_ci int msg_bytes = 0; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci /* Eat header */ 53f08c3bdfSopenharmony_ci for (;;) { 54f08c3bdfSopenharmony_ci int c = fgetc(f); 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci if (c == '\n' || c == EOF) 57f08c3bdfSopenharmony_ci break; 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci int cbytes, msgs; 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci /* 63f08c3bdfSopenharmony_ci * Sum queue and byte for all elements listed, which should equal 64f08c3bdfSopenharmony_ci * the data returned in the msginfo structure. 65f08c3bdfSopenharmony_ci */ 66f08c3bdfSopenharmony_ci while (fscanf(f, "%*i %*i %*i %i %i %*i %*i %*i %*i %*i %*i %*i %*i %*i", 67f08c3bdfSopenharmony_ci &cbytes, &msgs) > 0){ 68f08c3bdfSopenharmony_ci queue_cnt++; 69f08c3bdfSopenharmony_ci msg_cnt += msgs; 70f08c3bdfSopenharmony_ci msg_bytes += cbytes; 71f08c3bdfSopenharmony_ci } 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci if (info->msgpool != queue_cnt) { 74f08c3bdfSopenharmony_ci tst_res(TFAIL, "msgpool = %i, expected %i", 75f08c3bdfSopenharmony_ci info->msgpool, queue_cnt); 76f08c3bdfSopenharmony_ci } else { 77f08c3bdfSopenharmony_ci tst_res(TPASS, "queue_cnt = %i", queue_cnt); 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci if (info->msgmap != msg_cnt) { 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "msgmap = %i, expected %i", 82f08c3bdfSopenharmony_ci info->msgpool, msg_cnt); 83f08c3bdfSopenharmony_ci } else { 84f08c3bdfSopenharmony_ci tst_res(TPASS, "msg_cnt = %i", msg_cnt); 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci if (info->msgtql != msg_bytes) { 88f08c3bdfSopenharmony_ci tst_res(TFAIL, "msgtql = %i, expected %i", 89f08c3bdfSopenharmony_ci info->msgtql, msg_bytes); 90f08c3bdfSopenharmony_ci } else { 91f08c3bdfSopenharmony_ci tst_res(TPASS, "msg_bytes = %i", msg_bytes); 92f08c3bdfSopenharmony_ci } 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci fclose(f); 95f08c3bdfSopenharmony_ci} 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_cistatic void verify_msgctl(unsigned int n) 98f08c3bdfSopenharmony_ci{ 99f08c3bdfSopenharmony_ci struct tcases *tc = &tests[n]; 100f08c3bdfSopenharmony_ci int i, msgid, cnt = 0; 101f08c3bdfSopenharmony_ci struct msqid_ds buf; 102f08c3bdfSopenharmony_ci struct msginfo info; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci tst_res(TINFO, "Test MSG_STAT_ANY %s", tc->desc); 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci SAFE_SETEUID(*tc->uid); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci TEST(msgctl(0, MSG_INFO, (struct msqid_ds *)&info)); 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ci if (TST_RET == -1) { 111f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "msgctl(0, MSG_INFO, ...)"); 112f08c3bdfSopenharmony_ci return; 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci msgid = msgctl(TST_RET, MSG_STAT_ANY, &buf); 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci if (msgid == -1) { 118f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "MSG_INFO haven't returned a valid index"); 119f08c3bdfSopenharmony_ci } else { 120f08c3bdfSopenharmony_ci tst_res(TPASS, "MSG_INFO returned valid index %li to msgid %i", 121f08c3bdfSopenharmony_ci TST_RET, msgid); 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci for (i = 0; i <= TST_RET; i++) { 125f08c3bdfSopenharmony_ci if (msgctl(i, MSG_STAT_ANY, &buf) != -1) 126f08c3bdfSopenharmony_ci cnt++; 127f08c3bdfSopenharmony_ci } 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci if (cnt == info.msgpool) { 130f08c3bdfSopenharmony_ci tst_res(TPASS, "Counted used = %i", cnt); 131f08c3bdfSopenharmony_ci } else { 132f08c3bdfSopenharmony_ci tst_res(TFAIL, "Counted used = %i, msgpool = %i", 133f08c3bdfSopenharmony_ci cnt, info.msgpool); 134f08c3bdfSopenharmony_ci } 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci parse_proc_sysvipc(&info); 137f08c3bdfSopenharmony_ci} 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_cistatic void setup(void) 140f08c3bdfSopenharmony_ci{ 141f08c3bdfSopenharmony_ci struct msqid_ds temp_buf; 142f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM("nobody"); 143f08c3bdfSopenharmony_ci nobody_uid = ltpuser->pw_uid; 144f08c3bdfSopenharmony_ci root_uid = 0; 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci msg_id = SAFE_MSGGET(IPC_PRIVATE, IPC_CREAT | MSG_RW); 147f08c3bdfSopenharmony_ci SAFE_MSGSND(msg_id, "abcd", 4, 0); 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci TEST(msgctl(msg_id, MSG_STAT_ANY, &temp_buf)); 150f08c3bdfSopenharmony_ci if (TST_RET == -1) { 151f08c3bdfSopenharmony_ci if (TST_ERR == EINVAL) 152f08c3bdfSopenharmony_ci tst_brk(TCONF, "kernel doesn't support MSG_STAT_ANY"); 153f08c3bdfSopenharmony_ci else 154f08c3bdfSopenharmony_ci tst_brk(TBROK | TTERRNO, 155f08c3bdfSopenharmony_ci "Current environment doesn't permit MSG_STAT_ANY"); 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci} 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_cistatic void cleanup(void) 160f08c3bdfSopenharmony_ci{ 161f08c3bdfSopenharmony_ci if (msg_id >= 0) 162f08c3bdfSopenharmony_ci SAFE_MSGCTL(msg_id, IPC_RMID, NULL); 163f08c3bdfSopenharmony_ci} 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_cistatic struct tst_test test = { 166f08c3bdfSopenharmony_ci .setup = setup, 167f08c3bdfSopenharmony_ci .cleanup = cleanup, 168f08c3bdfSopenharmony_ci .test = verify_msgctl, 169f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tests), 170f08c3bdfSopenharmony_ci .needs_root = 1, 171f08c3bdfSopenharmony_ci}; 172