1/*
2 * Copyright (C) 2024 HiHope Open Source Organization.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <cerrno>
17#include <cstdio>
18#include <cstdlib>
19#include <csignal>
20#include <string>
21#include <vector>
22#include <fcntl.h>
23#include <malloc.h>
24#include <unistd.h>
25#include <arpa/inet.h>
26#include <gtest/gtest.h>
27#include <netinet/in.h>
28#include <sys/mman.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include "securec.h"
33
34using namespace testing::ext;
35
36class HatsMprotectTest : public testing::Test {
37public:
38    static void SetUpTestCase();
39    static void TearDownTestCase();
40    void SetUp();
41    void TearDown();
42private:
43};
44void HatsMprotectTest::SetUp()
45{
46}
47
48void HatsMprotectTest::TearDown()
49{
50}
51
52void HatsMprotectTest::SetUpTestCase()
53{
54}
55
56void HatsMprotectTest::TearDownTestCase()
57{
58}
59
60/*
61 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0100
62 * @tc.name   : MprotectWriteSuccess_0001
63 * @tc.desc   : mprotect changes the access protections to PROT_WRITE successfully.
64 * @tc.size   : MediumTest
65 * @tc.type   : Function
66 * @tc.level  : Level 1
67 */
68HWTEST_F(HatsMprotectTest, MprotectWriteSuccess_0001, Function | MediumTest | Level1)
69{
70    int ret;
71    int pagesize;
72    struct sigaction sa;
73
74    sa.sa_flags = SA_SIGINFO;
75    sigemptyset(&sa.sa_mask);
76    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
77
78    pagesize = sysconf(_SC_PAGE_SIZE);
79    EXPECT_NE(pagesize, -1);
80
81    // Allocate a buffer aligned on a page boundary; initial protection is PROT_WRITE.
82    void *buffer = memalign(pagesize, 4 * pagesize);
83    EXPECT_NE(buffer, nullptr);
84
85    ret = mprotect(buffer, pagesize, PROT_WRITE);
86    EXPECT_EQ(ret, 0);
87}
88
89/*
90 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0200
91 * @tc.name   : MprotectExeSuccess_0002
92 * @tc.desc   : mprotect changes the access protections to PROT_EXEC successfully.
93 * @tc.size   : MediumTest
94 * @tc.type   : Function
95 * @tc.level  : Level 1
96 */
97HWTEST_F(HatsMprotectTest, MprotectExeSuccess_0002, Function | MediumTest | Level1)
98{
99    int ret;
100    int pagesize;
101    struct sigaction sa;
102
103    sa.sa_flags = SA_SIGINFO;
104    sigemptyset(&sa.sa_mask);
105    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
106
107    pagesize = sysconf(_SC_PAGE_SIZE);
108    EXPECT_NE(pagesize, -1);
109
110    // Allocate a buffer aligned on a page boundary; initial protection is PROT_EXEC.
111    void *buf = memalign(pagesize, 4 * pagesize);
112    EXPECT_NE(buf, nullptr);
113
114    ret = mprotect(buf, pagesize, PROT_EXEC);
115    EXPECT_EQ(ret, 0);
116}
117
118/*
119 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0300
120 * @tc.name   : MprotectAddrInvalid_0003
121 * @tc.desc   : mprotect changes the access protections to PROT_READ failed for invalid address,error code is ENOMEM.
122 * @tc.size   : MediumTest
123 * @tc.type   : Function
124 * @tc.level  : Level 2
125 */
126HWTEST_F(HatsMprotectTest, MprotectAddrInvalid_0003, Function | MediumTest | Level2)
127{
128    int ret;
129    int pagesize;
130    struct sigaction sa;
131
132    sa.sa_flags = SA_SIGINFO;
133    sigemptyset(&sa.sa_mask);
134    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
135
136    pagesize = sysconf(_SC_PAGE_SIZE);
137    EXPECT_NE(pagesize, -1);
138
139    void *buf = nullptr;
140    errno = 0;
141    ret = mprotect(buf, pagesize, PROT_READ);
142    EXPECT_EQ(ret, -1);
143    EXPECT_EQ(errno, ENOMEM);
144}
145
146/*
147 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0400
148 * @tc.name   : MprotectFlagInvalid_0004
149 * @tc.desc   : mprotect changes the access protections to PROT_READ failed for flag invalid, error code is EINVAL.
150 * @tc.size   : MediumTest
151 * @tc.type   : Function
152 * @tc.level  : Level 2
153 */
154HWTEST_F(HatsMprotectTest, MprotectFlagInvalid_0004, Function | MediumTest | Level2)
155{
156    int ret;
157    int pagesize;
158    struct sigaction sa;
159
160    sa.sa_flags = SA_SIGINFO;
161    sigemptyset(&sa.sa_mask);
162    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
163
164    pagesize = sysconf(_SC_PAGE_SIZE);
165    EXPECT_NE(pagesize, -1);
166
167    // Allocate a buffer aligned on a page boundary; initial protection is invalid value of 0xFF.
168    void *buf = memalign(pagesize, 4 * pagesize);
169    EXPECT_NE(buf, nullptr);
170
171    errno = 0;
172    ret = mprotect(buf, pagesize, 0xFF);
173
174    EXPECT_EQ(ret, -1);
175    EXPECT_EQ(errno, EINVAL);
176}
177
178/*
179 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0500
180 * @tc.name   : MprotectUpDownInvalid_0005
181 * @tc.desc   : When PROT_GROWSUP and PROT_GROWSDOWN specified change access protections failed,
182 * @tc.size   : MediumTest
183 * @tc.type   : Function
184 * @tc.level  : Level 2
185 */
186HWTEST_F(HatsMprotectTest, MprotectUpDownInvalid_0005, Function | MediumTest | Level2)
187{
188    int ret;
189    int pagesize;
190    struct sigaction sa;
191
192    sa.sa_flags = SA_SIGINFO;
193    sigemptyset(&sa.sa_mask);
194    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
195
196    pagesize = sysconf(_SC_PAGE_SIZE);
197    EXPECT_NE(pagesize, -1);
198
199    // Allocate a buffer aligned on a page boundary; initial protection are PROT_GROWSUP and PROT_GROWSDOWN.
200    void *buf = memalign(pagesize, 4 * pagesize);
201    EXPECT_NE(buf, nullptr);
202
203    errno = 0;
204    ret = mprotect(buf, pagesize, PROT_GROWSUP | PROT_GROWSDOWN);
205
206    EXPECT_EQ(ret, -1);
207    EXPECT_EQ(errno, EINVAL);
208}
209
210/*
211 * @tc.number : SUB_KERNEL_SYSCALL_MPROTECT_0600
212 * @tc.name   : MprotectPROT_NONETestSuccess_0006
213 * @tc.desc   : mprotect PROT_NONE flag test successfully.
214 * @tc.size   : MediumTest
215 * @tc.type   : Function
216 * @tc.level  : Level 1
217 */
218HWTEST_F(HatsMprotectTest, MprotectPROT_NONETestSuccess_0006, Function | MediumTest | Level1)
219{
220    int ret;
221    int pagesize;
222    struct sigaction sa;
223
224    sa.sa_flags = SA_SIGINFO;
225    sigemptyset(&sa.sa_mask);
226    EXPECT_NE(sigaction(SIGSEGV, &sa, nullptr), -1);
227
228    pagesize = sysconf(_SC_PAGE_SIZE);
229    EXPECT_NE(pagesize, -1);
230
231    void *buffer = memalign(pagesize, 4 * pagesize);
232    EXPECT_NE(buffer, nullptr);
233
234    ret = mprotect(buffer, pagesize, PROT_NONE);
235    EXPECT_EQ(ret, 0);
236}
237