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 <pwd.h>
12f08c3bdfSopenharmony_ci#include <mqueue.h>
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ci#include "tst_test.h"
15f08c3bdfSopenharmony_ci#include "tst_safe_posix_ipc.h"
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#define QUEUE_NAME	"/test_mqueue"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cistatic uid_t euid;
20f08c3bdfSopenharmony_cistatic struct passwd *pw;
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistruct test_case {
23f08c3bdfSopenharmony_ci	int as_nobody;
24f08c3bdfSopenharmony_ci	char *qname;
25f08c3bdfSopenharmony_ci	int ret;
26f08c3bdfSopenharmony_ci	int err;
27f08c3bdfSopenharmony_ci};
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_cistatic struct test_case tcase[] = {
30f08c3bdfSopenharmony_ci	{
31f08c3bdfSopenharmony_ci		.qname = QUEUE_NAME,
32f08c3bdfSopenharmony_ci		.ret = 0,
33f08c3bdfSopenharmony_ci		.err = 0,
34f08c3bdfSopenharmony_ci	},
35f08c3bdfSopenharmony_ci	{
36f08c3bdfSopenharmony_ci		.as_nobody = 1,
37f08c3bdfSopenharmony_ci		.qname = QUEUE_NAME,
38f08c3bdfSopenharmony_ci		.ret = -1,
39f08c3bdfSopenharmony_ci		.err = EACCES,
40f08c3bdfSopenharmony_ci	},
41f08c3bdfSopenharmony_ci	{
42f08c3bdfSopenharmony_ci		.qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
43f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
44f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
45f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
46f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
47f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
48f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaa",
49f08c3bdfSopenharmony_ci		.ret = -1,
50f08c3bdfSopenharmony_ci		.err = ENOENT,
51f08c3bdfSopenharmony_ci	},
52f08c3bdfSopenharmony_ci	{
53f08c3bdfSopenharmony_ci		.qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
54f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
55f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
56f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
57f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
58f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
59f08c3bdfSopenharmony_ci			"aaaaaaaaaaaaaaaa",
60f08c3bdfSopenharmony_ci		.ret = -1,
61f08c3bdfSopenharmony_ci		.err = ENAMETOOLONG,
62f08c3bdfSopenharmony_ci	},
63f08c3bdfSopenharmony_ci};
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_civoid setup(void)
66f08c3bdfSopenharmony_ci{
67f08c3bdfSopenharmony_ci	euid = geteuid();
68f08c3bdfSopenharmony_ci	pw = SAFE_GETPWNAM("nobody");
69f08c3bdfSopenharmony_ci}
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_cistatic void do_test(unsigned int i)
72f08c3bdfSopenharmony_ci{
73f08c3bdfSopenharmony_ci	struct test_case *tc = &tcase[i];
74f08c3bdfSopenharmony_ci	mqd_t fd;
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_ci	tst_res(TINFO, "queue name %s", tc->qname);
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	/*
79f08c3bdfSopenharmony_ci	 * When test ended with SIGTERM etc, mq descriptor is left remains.
80f08c3bdfSopenharmony_ci	 * So we delete it first.
81f08c3bdfSopenharmony_ci	 */
82f08c3bdfSopenharmony_ci	mq_unlink(QUEUE_NAME);
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	/* prepare */
85f08c3bdfSopenharmony_ci	fd = SAFE_MQ_OPEN(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL);
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	if (tc->as_nobody && seteuid(pw->pw_uid)) {
88f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "seteuid failed");
89f08c3bdfSopenharmony_ci		goto EXIT;
90f08c3bdfSopenharmony_ci	}
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_ci	/* test */
93f08c3bdfSopenharmony_ci	TEST(mq_unlink(tc->qname));
94f08c3bdfSopenharmony_ci	if (TST_ERR != tc->err || TST_RET != tc->ret) {
95f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO, "mq_unlink returned %ld, expected %d,"
96f08c3bdfSopenharmony_ci			" expected errno %s (%d)", TST_RET,
97f08c3bdfSopenharmony_ci			tc->ret, tst_strerrno(tc->err), tc->err);
98f08c3bdfSopenharmony_ci	} else {
99f08c3bdfSopenharmony_ci		tst_res(TPASS | TTERRNO, "mq_unlink returned %ld", TST_RET);
100f08c3bdfSopenharmony_ci	}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ciEXIT:
103f08c3bdfSopenharmony_ci	/* cleanup */
104f08c3bdfSopenharmony_ci	if (tc->as_nobody && seteuid(euid) == -1)
105f08c3bdfSopenharmony_ci		tst_res(TWARN | TERRNO, "seteuid back to %d failed", euid);
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	if (fd > 0 && close(fd))
108f08c3bdfSopenharmony_ci		tst_res(TWARN | TERRNO, "close(fd) failed");
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_ci	mq_unlink(QUEUE_NAME);
111f08c3bdfSopenharmony_ci}
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_cistatic struct tst_test test = {
114f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcase),
115f08c3bdfSopenharmony_ci	.test = do_test,
116f08c3bdfSopenharmony_ci	.needs_root = 1,
117f08c3bdfSopenharmony_ci	.setup = setup,
118f08c3bdfSopenharmony_ci};
119