1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd 4f08c3bdfSopenharmony_ci * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>, 5f08c3bdfSopenharmony_ci * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>, 6f08c3bdfSopenharmony_ci * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp> 7f08c3bdfSopenharmony_ci * Copyright (c) 2016 Linux Test Project 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ci#include <errno.h> 11f08c3bdfSopenharmony_ci#include <mqueue.h> 12f08c3bdfSopenharmony_ci#include <pwd.h> 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include "tst_test.h" 15f08c3bdfSopenharmony_ci#include "tst_safe_file_ops.h" 16f08c3bdfSopenharmony_ci#include "tst_safe_posix_ipc.h" 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#define QUEUE_NAME "/test_mqueue" 19f08c3bdfSopenharmony_ci#define QUEUE_INIT "/init_mqueue" 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_cistatic uid_t euid; 22f08c3bdfSopenharmony_cistatic struct passwd *pw; 23f08c3bdfSopenharmony_cistatic char *qname; 24f08c3bdfSopenharmony_cistatic struct rlimit rlim; 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_cistatic mqd_t fd, fd2; 27f08c3bdfSopenharmony_cistatic mqd_t fd3 = -1; 28f08c3bdfSopenharmony_cistatic int max_queues; 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistruct test_case { 31f08c3bdfSopenharmony_ci const char *desc; 32f08c3bdfSopenharmony_ci char *qname; 33f08c3bdfSopenharmony_ci int oflag; 34f08c3bdfSopenharmony_ci struct mq_attr *rq; 35f08c3bdfSopenharmony_ci int ret; 36f08c3bdfSopenharmony_ci int err; 37f08c3bdfSopenharmony_ci void (*setup)(void); 38f08c3bdfSopenharmony_ci void (*cleanup)(void); 39f08c3bdfSopenharmony_ci}; 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#define PROC_MAX_QUEUES "/proc/sys/fs/mqueue/queues_max" 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic void create_queue(void); 44f08c3bdfSopenharmony_cistatic void unlink_queue(void); 45f08c3bdfSopenharmony_cistatic void set_rlimit(void); 46f08c3bdfSopenharmony_cistatic void restore_rlimit(void); 47f08c3bdfSopenharmony_cistatic void set_max_queues(void); 48f08c3bdfSopenharmony_cistatic void restore_max_queues(void); 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic struct test_case tcase[] = { 51f08c3bdfSopenharmony_ci { 52f08c3bdfSopenharmony_ci .desc = "NORMAL", 53f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 54f08c3bdfSopenharmony_ci .oflag = O_CREAT, 55f08c3bdfSopenharmony_ci .rq = &(struct mq_attr){.mq_maxmsg = 20, .mq_msgsize = 16384}, 56f08c3bdfSopenharmony_ci .ret = 0, 57f08c3bdfSopenharmony_ci .err = 0, 58f08c3bdfSopenharmony_ci }, 59f08c3bdfSopenharmony_ci { 60f08c3bdfSopenharmony_ci .desc = "NORMAL", 61f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 62f08c3bdfSopenharmony_ci .oflag = O_CREAT, 63f08c3bdfSopenharmony_ci .ret = 0, 64f08c3bdfSopenharmony_ci .err = 0, 65f08c3bdfSopenharmony_ci }, 66f08c3bdfSopenharmony_ci { 67f08c3bdfSopenharmony_ci .desc = "NORMAL", 68f08c3bdfSopenharmony_ci .qname = "/caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 69f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 70f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 71f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 72f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 73f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 74f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaa", 75f08c3bdfSopenharmony_ci .oflag = O_CREAT, 76f08c3bdfSopenharmony_ci .ret = 0, 77f08c3bdfSopenharmony_ci .err = 0, 78f08c3bdfSopenharmony_ci }, 79f08c3bdfSopenharmony_ci { 80f08c3bdfSopenharmony_ci .desc = "NORMAL", 81f08c3bdfSopenharmony_ci .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 82f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 83f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 84f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 85f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 86f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 87f08c3bdfSopenharmony_ci "aaaaaaaaaaaaaaaa", 88f08c3bdfSopenharmony_ci .oflag = O_CREAT, 89f08c3bdfSopenharmony_ci .ret = -1, 90f08c3bdfSopenharmony_ci .err = ENAMETOOLONG, 91f08c3bdfSopenharmony_ci }, 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci { 94f08c3bdfSopenharmony_ci .desc = "NORMAL", 95f08c3bdfSopenharmony_ci .qname = "", 96f08c3bdfSopenharmony_ci .oflag = O_CREAT, 97f08c3bdfSopenharmony_ci .ret = -1, 98f08c3bdfSopenharmony_ci .err = EINVAL, 99f08c3bdfSopenharmony_ci }, 100f08c3bdfSopenharmony_ci { 101f08c3bdfSopenharmony_ci .desc = "NORMAL", 102f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 103f08c3bdfSopenharmony_ci .ret = -1, 104f08c3bdfSopenharmony_ci .err = EACCES, 105f08c3bdfSopenharmony_ci .setup = create_queue, 106f08c3bdfSopenharmony_ci .cleanup = unlink_queue, 107f08c3bdfSopenharmony_ci }, 108f08c3bdfSopenharmony_ci { 109f08c3bdfSopenharmony_ci .desc = "NORMAL", 110f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 111f08c3bdfSopenharmony_ci .oflag = O_CREAT | O_EXCL, 112f08c3bdfSopenharmony_ci .ret = -1, 113f08c3bdfSopenharmony_ci .err = EEXIST, 114f08c3bdfSopenharmony_ci .setup = create_queue, 115f08c3bdfSopenharmony_ci .cleanup = unlink_queue, 116f08c3bdfSopenharmony_ci }, 117f08c3bdfSopenharmony_ci { 118f08c3bdfSopenharmony_ci .desc = "NO_FILE", 119f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 120f08c3bdfSopenharmony_ci .oflag = O_CREAT, 121f08c3bdfSopenharmony_ci .ret = -1, 122f08c3bdfSopenharmony_ci .err = EMFILE, 123f08c3bdfSopenharmony_ci .setup = set_rlimit, 124f08c3bdfSopenharmony_ci .cleanup = restore_rlimit, 125f08c3bdfSopenharmony_ci }, 126f08c3bdfSopenharmony_ci { 127f08c3bdfSopenharmony_ci .desc = "NORMAL", 128f08c3bdfSopenharmony_ci .qname = "/notexist", 129f08c3bdfSopenharmony_ci .oflag = 0, 130f08c3bdfSopenharmony_ci .ret = -1, 131f08c3bdfSopenharmony_ci .err = ENOENT, 132f08c3bdfSopenharmony_ci }, 133f08c3bdfSopenharmony_ci { 134f08c3bdfSopenharmony_ci .desc = "NO_SPACE", 135f08c3bdfSopenharmony_ci .qname = QUEUE_NAME, 136f08c3bdfSopenharmony_ci .oflag = O_CREAT, 137f08c3bdfSopenharmony_ci .ret = -1, 138f08c3bdfSopenharmony_ci .err = ENOSPC, 139f08c3bdfSopenharmony_ci .setup = set_max_queues, 140f08c3bdfSopenharmony_ci .cleanup = restore_max_queues, 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci}; 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_cistatic void create_queue(void) 145f08c3bdfSopenharmony_ci{ 146f08c3bdfSopenharmony_ci fd2 = SAFE_MQ_OPEN(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL); 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci SAFE_SETEUID(pw->pw_uid); 149f08c3bdfSopenharmony_ci} 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_cistatic void unlink_queue(void) 152f08c3bdfSopenharmony_ci{ 153f08c3bdfSopenharmony_ci SAFE_SETEUID(euid); 154f08c3bdfSopenharmony_ci if (fd2 > 0) 155f08c3bdfSopenharmony_ci SAFE_CLOSE(fd2); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci if (mq_unlink(QUEUE_NAME)) 158f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "mq_close(" QUEUE_NAME ") failed"); 159f08c3bdfSopenharmony_ci} 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_cistatic void set_max_queues(void) 163f08c3bdfSopenharmony_ci{ 164f08c3bdfSopenharmony_ci SAFE_FILE_SCANF(PROC_MAX_QUEUES, "%d", &max_queues); 165f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PROC_MAX_QUEUES, "%d", 1); 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci SAFE_SETEUID(pw->pw_uid); 168f08c3bdfSopenharmony_ci} 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_cistatic void restore_max_queues(void) 171f08c3bdfSopenharmony_ci{ 172f08c3bdfSopenharmony_ci SAFE_SETEUID(euid); 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci SAFE_FILE_PRINTF(PROC_MAX_QUEUES, "%d", max_queues); 175f08c3bdfSopenharmony_ci} 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_cistatic void set_rlimit(void) 178f08c3bdfSopenharmony_ci{ 179f08c3bdfSopenharmony_ci if (rlim.rlim_cur > 0) { 180f08c3bdfSopenharmony_ci struct rlimit r; 181f08c3bdfSopenharmony_ci r.rlim_cur = 0; 182f08c3bdfSopenharmony_ci r.rlim_max = rlim.rlim_max; 183f08c3bdfSopenharmony_ci SAFE_SETRLIMIT(RLIMIT_NOFILE, &r); 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci} 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_cistatic void restore_rlimit(void) 188f08c3bdfSopenharmony_ci{ 189f08c3bdfSopenharmony_ci SAFE_SETRLIMIT(RLIMIT_NOFILE, &rlim); 190f08c3bdfSopenharmony_ci} 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_cistatic void setup(void) 193f08c3bdfSopenharmony_ci{ 194f08c3bdfSopenharmony_ci euid = geteuid(); 195f08c3bdfSopenharmony_ci pw = SAFE_GETPWNAM("nobody"); 196f08c3bdfSopenharmony_ci SAFE_GETRLIMIT(RLIMIT_NOFILE, &rlim); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci fd3 = SAFE_MQ_OPEN(QUEUE_INIT, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL); 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_cistatic void cleanup(void) 202f08c3bdfSopenharmony_ci{ 203f08c3bdfSopenharmony_ci if (fd > 0) 204f08c3bdfSopenharmony_ci mq_close(fd); 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci if (fd2 > 0) 207f08c3bdfSopenharmony_ci mq_close(fd2); 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci if (fd3 > 0 && mq_close(fd3)) 210f08c3bdfSopenharmony_ci tst_res(TWARN | TERRNO, "mq_close(%s) failed", QUEUE_INIT); 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci if (mq_unlink(QUEUE_INIT)) 213f08c3bdfSopenharmony_ci tst_res(TWARN | TERRNO, "mq_unlink(%s) failed", QUEUE_INIT); 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_ci mq_unlink(qname); 216f08c3bdfSopenharmony_ci} 217f08c3bdfSopenharmony_ci 218f08c3bdfSopenharmony_cistatic void do_test(unsigned int i) 219f08c3bdfSopenharmony_ci{ 220f08c3bdfSopenharmony_ci struct test_case *tc = &tcase[i]; 221f08c3bdfSopenharmony_ci struct mq_attr oldattr; 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci qname = tc->qname; 224f08c3bdfSopenharmony_ci fd = fd2 = -1; 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci tst_res(TINFO, "queue name \"%s\"", qname); 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci if (tc->setup) 229f08c3bdfSopenharmony_ci tc->setup(); 230f08c3bdfSopenharmony_ci 231f08c3bdfSopenharmony_ci TEST(fd = mq_open(qname, tc->oflag, S_IRWXU, tc->rq)); 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_ci if (fd > 0 && tc->rq) { 234f08c3bdfSopenharmony_ci if (mq_getattr(fd, &oldattr) < 0) { 235f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "mq_getattr failed"); 236f08c3bdfSopenharmony_ci goto CLEANUP; 237f08c3bdfSopenharmony_ci } 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci if (oldattr.mq_maxmsg != tc->rq->mq_maxmsg 240f08c3bdfSopenharmony_ci || oldattr.mq_msgsize != tc->rq->mq_msgsize) { 241f08c3bdfSopenharmony_ci tst_res(TFAIL, "wrong mq_attr: " 242f08c3bdfSopenharmony_ci "mq_maxmsg expected %ld return %ld, " 243f08c3bdfSopenharmony_ci "mq_msgsize expected %ld return %ld", 244f08c3bdfSopenharmony_ci tc->rq->mq_maxmsg, oldattr.mq_maxmsg, tc->rq->mq_msgsize, 245f08c3bdfSopenharmony_ci oldattr.mq_msgsize); 246f08c3bdfSopenharmony_ci goto CLEANUP; 247f08c3bdfSopenharmony_ci } 248f08c3bdfSopenharmony_ci } 249f08c3bdfSopenharmony_ci 250f08c3bdfSopenharmony_ci if (tc->ret == 0) { 251f08c3bdfSopenharmony_ci if (TST_RET < 0) { 252f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "%s wrong return code: %ld", 253f08c3bdfSopenharmony_ci tc->desc, TST_RET); 254f08c3bdfSopenharmony_ci } else { 255f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "%s returned: %ld", 256f08c3bdfSopenharmony_ci tc->desc, TST_RET); 257f08c3bdfSopenharmony_ci } 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci goto CLEANUP; 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci if (TST_ERR != tc->err) { 263f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "%s expected errno: %d", 264f08c3bdfSopenharmony_ci tc->desc, TST_ERR); 265f08c3bdfSopenharmony_ci goto CLEANUP; 266f08c3bdfSopenharmony_ci } 267f08c3bdfSopenharmony_ci 268f08c3bdfSopenharmony_ci if (TST_RET != tc->ret) { 269f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "%s wrong return code: %ld", 270f08c3bdfSopenharmony_ci tc->desc, TST_RET); 271f08c3bdfSopenharmony_ci } else { 272f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "%s returned: %ld", 273f08c3bdfSopenharmony_ci tc->desc, TST_RET); 274f08c3bdfSopenharmony_ci } 275f08c3bdfSopenharmony_ci 276f08c3bdfSopenharmony_ciCLEANUP: 277f08c3bdfSopenharmony_ci if (tc->cleanup) 278f08c3bdfSopenharmony_ci tc->cleanup(); 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci if (TST_RET != -1) { 281f08c3bdfSopenharmony_ci if (fd > 0) 282f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 283f08c3bdfSopenharmony_ci mq_unlink(qname); 284f08c3bdfSopenharmony_ci } 285f08c3bdfSopenharmony_ci} 286f08c3bdfSopenharmony_ci 287f08c3bdfSopenharmony_cistatic struct tst_test test = { 288f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcase), 289f08c3bdfSopenharmony_ci .test = do_test, 290f08c3bdfSopenharmony_ci .needs_root = 1, 291f08c3bdfSopenharmony_ci .setup = setup, 292f08c3bdfSopenharmony_ci .cleanup = cleanup, 293f08c3bdfSopenharmony_ci}; 294