1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include <fstream>
31 #include <iostream>
32 #include "It_container_test.h"
33 using namespace std;
34
childFunc(void * arg)35 static int childFunc(void *arg)
36 {
37 int ret;
38 (void)arg;
39 char msgrcd[MQUEUE_STANDARD_NAME_LENGTH] = {0};
40 char mqname[] = "/testMQueue005";
41 const char msgptr[] = "childMsg";
42 struct mq_attr attr = { 0 };
43 mqd_t mqueue;
44 attr.mq_msgsize = MQUEUE_TEST_SIZE;
45 attr.mq_maxmsg = MQUEUE_TEST_MAX_MSG;
46
47 mqueue = mq_open(mqname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, &attr);
48 if (mqueue == (mqd_t)-1) {
49 goto EXIT1;
50 }
51 ret = mq_send(mqueue, msgptr, strlen(msgptr), 0);
52 if (ret != 0) {
53 goto EXIT1;
54 }
55 ret = mq_receive(mqueue, msgrcd, MQUEUE_STANDARD_NAME_LENGTH, NULL);
56 if (ret != strlen(msgptr)) {
57 goto EXIT1;
58 }
59 if (strncmp(msgrcd, msgptr, strlen(msgptr)) != 0) {
60 goto EXIT1;
61 }
62
63 EXIT1:
64 if (mqueue >= 0) {
65 ret = mq_close(mqueue);
66 if (ret != 0) {
67 return EXIT_CODE_ERRNO_1;
68 }
69 ret = mq_unlink(mqname);
70 if (ret != 0) {
71 return EXIT_CODE_ERRNO_2;
72 }
73 }
74 return EXIT_CODE_ERRNO_7;
75 }
76
IpcContainerUnshare(void)77 static void IpcContainerUnshare(void)
78 {
79 int status, exitCode, ret;
80 int arg = CHILD_FUNC_ARG;
81 char *stack = (char *)mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, CLONE_STACK_MMAP_FLAG, -1, 0);
82 ASSERT_NE(stack, nullptr);
83 char *stackTop = stack + STACK_SIZE;
84 struct mq_attr attr = { 0 };
85 attr.mq_msgsize = MQUEUE_TEST_SIZE;
86 attr.mq_maxmsg = MQUEUE_TEST_MAX_MSG;
87 struct sigevent notification;
88 notification.sigev_notify = 5; /* 5: test data */
89 char msgrcd[MQUEUE_STANDARD_NAME_LENGTH] = {0};
90 char mqname[] = "/testMQueue006";
91 const char msgptr[] = "parentMsg";
92
93 ret = unshare(CLONE_NEWIPC);
94 ASSERT_EQ(ret, 0);
95
96 mqd_t mqueue = mq_open(mqname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR, &attr);
97 MQueueFinalizer mQueueFinalizer(mqueue, mqname);
98
99 ASSERT_NE(mqueue, (mqd_t)-1);
100
101 ret = mq_notify(mqueue, ¬ification);
102 ASSERT_EQ(ret, -1);
103 ASSERT_EQ(errno, EINVAL);
104
105 notification.sigev_notify = SIGEV_THREAD;
106 ret = mq_notify(mqueue, ¬ification);
107 ASSERT_EQ(ret, -1);
108 ASSERT_EQ(errno, ENOTSUP);
109
110 notification.sigev_notify = SIGEV_NONE;
111
112 ret = mq_notify(-1, ¬ification);
113 ASSERT_EQ(ret, -1);
114 ASSERT_EQ(errno, EBADF);
115
116 ret = mq_notify(mqueue, ¬ification);
117 ASSERT_EQ(ret, 0);
118
119 (void)memset_s(&attr, sizeof(attr), 0, sizeof(attr));
120 ret = mq_getattr(mqueue, &attr);
121 ASSERT_EQ(ret, 0);
122
123 attr.mq_flags |= O_NONBLOCK;
124 ret = mq_setattr(mqueue, &attr, NULL);
125 ASSERT_EQ(ret, 0);
126
127 ret = mq_getattr(mqueue, &attr);
128 ASSERT_EQ(ret, 0);
129
130 ret = mq_send(mqueue, msgptr, strlen(msgptr), 0);
131 ASSERT_EQ(ret, 0);
132
133 pid_t pid = clone(childFunc, stackTop, CLONE_NEWIPC | SIGCHLD, &arg);
134 ASSERT_NE(pid, -1);
135
136 ret = waitpid(pid, &status, 0);
137 ASSERT_EQ(ret, pid);
138
139 ret = WIFEXITED(status);
140 ASSERT_NE(pid, 0);
141
142 exitCode = WEXITSTATUS(status);
143 ASSERT_EQ(exitCode, EXIT_CODE_ERRNO_7);
144
145 ret = mq_notify(mqueue, nullptr);
146 ASSERT_EQ(ret, 0);
147
148 ret = mq_receive(mqueue, msgrcd, MQUEUE_STANDARD_NAME_LENGTH, NULL);
149 ASSERT_EQ(ret, strlen(msgptr));
150 ASSERT_STREQ(msgrcd, msgptr);
151 }
152
ItIpcContainer003(void)153 void ItIpcContainer003(void)
154 {
155 auto pid = fork();
156 ASSERT_TRUE(pid != -1);
157 if (pid == 0) {
158 IpcContainerUnshare();
159 exit(0);
160 }
161 auto ret = waitpid(pid, NULL, 0);
162 ASSERT_EQ(ret, pid);
163 }
164