1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd
4 * Author(s): Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
5 * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
6 * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
7 * Copyright (c) 2016 Linux Test Project
8 */
9
10 #include <errno.h>
11 #include <pwd.h>
12 #include <mqueue.h>
13
14 #include "tst_test.h"
15 #include "tst_safe_posix_ipc.h"
16
17 #define QUEUE_NAME "/test_mqueue"
18
19 static uid_t euid;
20 static struct passwd *pw;
21
22 struct test_case {
23 int as_nobody;
24 char *qname;
25 int ret;
26 int err;
27 };
28
29 static struct test_case tcase[] = {
30 {
31 .qname = QUEUE_NAME,
32 .ret = 0,
33 .err = 0,
34 },
35 {
36 .as_nobody = 1,
37 .qname = QUEUE_NAME,
38 .ret = -1,
39 .err = EACCES,
40 },
41 {
42 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
43 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
44 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
45 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
46 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
47 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
48 "aaaaaaaaaaaaaaa",
49 .ret = -1,
50 .err = ENOENT,
51 },
52 {
53 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
54 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
55 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
56 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
57 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
58 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
59 "aaaaaaaaaaaaaaaa",
60 .ret = -1,
61 .err = ENAMETOOLONG,
62 },
63 };
64
setup(void)65 void setup(void)
66 {
67 euid = geteuid();
68 pw = SAFE_GETPWNAM("nobody");
69 }
70
do_test(unsigned int i)71 static void do_test(unsigned int i)
72 {
73 struct test_case *tc = &tcase[i];
74 mqd_t fd;
75
76 tst_res(TINFO, "queue name %s", tc->qname);
77
78 /*
79 * When test ended with SIGTERM etc, mq descriptor is left remains.
80 * So we delete it first.
81 */
82 mq_unlink(QUEUE_NAME);
83
84 /* prepare */
85 fd = SAFE_MQ_OPEN(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL);
86
87 if (tc->as_nobody && seteuid(pw->pw_uid)) {
88 tst_res(TBROK | TERRNO, "seteuid failed");
89 goto EXIT;
90 }
91
92 /* test */
93 TEST(mq_unlink(tc->qname));
94 if (TST_ERR != tc->err || TST_RET != tc->ret) {
95 tst_res(TFAIL | TTERRNO, "mq_unlink returned %ld, expected %d,"
96 " expected errno %s (%d)", TST_RET,
97 tc->ret, tst_strerrno(tc->err), tc->err);
98 } else {
99 tst_res(TPASS | TTERRNO, "mq_unlink returned %ld", TST_RET);
100 }
101
102 EXIT:
103 /* cleanup */
104 if (tc->as_nobody && seteuid(euid) == -1)
105 tst_res(TWARN | TERRNO, "seteuid back to %d failed", euid);
106
107 if (fd > 0 && close(fd))
108 tst_res(TWARN | TERRNO, "close(fd) failed");
109
110 mq_unlink(QUEUE_NAME);
111 }
112
113 static struct tst_test test = {
114 .tcnt = ARRAY_SIZE(tcase),
115 .test = do_test,
116 .needs_root = 1,
117 .setup = setup,
118 };
119