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 "It_container_test.h"
31 using namespace std;
32 
33 static const char testBuf[] = "test shm";
34 struct shared_use_st {
35     char test[SHM_TEST_DATA_SIZE];
36 };
37 
childFunc(void *arg)38 static int childFunc(void *arg)
39 {
40     struct shared_use_st *shared = NULL;
41     int ret;
42     (void)arg;
43     char *containerType = "ipc";
44     auto linkBuffer = ReadlinkContainer(getpid(), containerType);
45 
46     ret = unshare(CLONE_NEWIPC);
47     if (ret != 0) {
48         return EXIT_CODE_ERRNO_1;
49     }
50 
51     auto linkBuffer1 = ReadlinkContainer(getpid(), containerType);
52     ret = linkBuffer.compare(linkBuffer1);
53     if (ret == 0) {
54         return EXIT_CODE_ERRNO_2;
55     }
56 
57     int shmid = shmget((key_t)SHM_TEST_KEY1, sizeof(struct shared_use_st), SHM_TEST_OPEN_PERM | IPC_CREAT);
58     if (shmid == -1) {
59         return EXIT_CODE_ERRNO_3;
60     }
61 
62     void *shm = shmat(shmid, 0, 0);
63     if (shm == reinterpret_cast<void *>(-1)) {
64         shmctl(shmid, IPC_RMID, 0);
65         return EXIT_CODE_ERRNO_4;
66     }
67 
68     shared = (struct shared_use_st *)shm;
69     ret = strncmp(shared->test, testBuf, strlen(testBuf));
70     if (ret == 0) {
71         shmdt(shm);
72         shmctl(shmid, IPC_RMID, 0);
73         return EXIT_CODE_ERRNO_5;
74     }
75 
76     ret = shmdt(shm);
77     if (ret == -1) {
78         shmctl(shmid, IPC_RMID, 0);
79         return EXIT_CODE_ERRNO_6;
80     }
81 
82     ret = shmctl(shmid, IPC_RMID, 0);
83     if (ret == -1) {
84         return EXIT_CODE_ERRNO_7;
85     }
86     return 0;
87 }
88 
testChild(void *arg)89 static int testChild(void *arg)
90 {
91     (void)arg;
92     int ret;
93     struct shared_use_st *shared = NULL;
94     int status;
95     int exitCode;
96     int pid;
97 
98     char *stack = (char *)mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK,
99                                -1, 0);
100     if (stack == nullptr) {
101         return EXIT_CODE_ERRNO_17;
102     }
103     char *stackTop = stack + STACK_SIZE;
104 
105     int shmid = shmget((key_t)SHM_TEST_KEY1, sizeof(struct shared_use_st), SHM_TEST_OPEN_PERM | IPC_CREAT);
106     if (shmid == -1) {
107         return EXIT_CODE_ERRNO_8;
108     }
109 
110     void *shm = shmat(shmid, 0, 0);
111     if (shm == reinterpret_cast<void *>(-1)) {
112         shmctl(shmid, IPC_RMID, 0);
113         return EXIT_CODE_ERRNO_9;
114     }
115 
116     shared = (struct shared_use_st *)shm;
117     ret = memcpy_s(shared->test, sizeof(struct shared_use_st), testBuf, sizeof(testBuf));
118     if (ret != 0) {
119         shmdt(shm);
120         shmctl(shmid, IPC_RMID, 0);
121         return EXIT_CODE_ERRNO_10;
122     }
123 
124     pid = clone(childFunc, stackTop, SIGCHLD, &arg);
125     if (pid == -1) {
126         shmdt(shm);
127         shmctl(shmid, IPC_RMID, 0);
128         return EXIT_CODE_ERRNO_11;
129     }
130 
131     ret = waitpid(pid, &status, 0);
132     if (ret != pid) {
133         shmdt(shm);
134         shmctl(shmid, IPC_RMID, 0);
135         return EXIT_CODE_ERRNO_12;
136     }
137 
138     ret = WIFEXITED(status);
139     if (ret == 0) {
140         shmdt(shm);
141         shmctl(shmid, IPC_RMID, 0);
142         return EXIT_CODE_ERRNO_13;
143     }
144 
145     exitCode = WEXITSTATUS(status);
146     if (exitCode != 0) {
147         shmdt(shm);
148         shmctl(shmid, IPC_RMID, 0);
149         return EXIT_CODE_ERRNO_14;
150     }
151 
152     ret = shmdt(shm);
153     if (ret == -1) {
154         shmctl(shmid, IPC_RMID, 0);
155         return EXIT_CODE_ERRNO_15;
156     }
157 
158     ret = shmctl(shmid, IPC_RMID, 0);
159     if (ret == -1) {
160         return EXIT_CODE_ERRNO_16;
161     }
162     return 0;
163 }
164 
ItIpcContainer005(void)165 void ItIpcContainer005(void)
166 {
167     int ret;
168     int status;
169     char *stack = (char *)mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK,
170                                -1, 0);
171     ASSERT_NE(stack, nullptr);
172 
173     char *stackTop = stack + STACK_SIZE;
174 
175     int arg = CHILD_FUNC_ARG;
176     auto pid = clone(testChild, stackTop, CLONE_NEWIPC | SIGCHLD, &arg);
177     ASSERT_NE(pid, -1);
178 
179     ret = waitpid(pid, &status, 0);
180     ASSERT_EQ(ret, pid);
181 
182     ret = WIFEXITED(status);
183     ASSERT_NE(ret, 0);
184 
185     int exitCode = WEXITSTATUS(status);
186     ASSERT_EQ(exitCode, 0);
187 }
188