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 <string>
20 #include <vector>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <gtest/gtest.h>
24 #include <sys/file.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include "securec.h"
28 
29 using namespace testing::ext;
30 using namespace std;
31 
32 static const int PATH_MAX_LEN = 128;
33 static const char *TEST_FILE = "/data/local/tmp/fchownat.txt";
34 static const char *TEST_FILE_PATH = "/data/local/tmp";
35 static const char *TEST_FILE_NAME = "fchownat.txt";
36 static const char *SYMBOL_LINK_NAME = "TestFchmodatSymlink";
37 mode_t MODE_0644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
38 mode_t MODE_0755 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
39 
40 class FchownatApiTest : public testing::Test {
41 public:
42     static void SetUpTestCase();
43     static void TearDownTestCase();
44     void SetUp();
45     void TearDown();
46 private:
47 };
SetUp()48 void FchownatApiTest::SetUp()
49 {
50 }
TearDown()51 void FchownatApiTest::TearDown()
52 {
53 }
SetUpTestCase()54 void FchownatApiTest::SetUpTestCase()
55 {
56 }
TearDownTestCase()57 void FchownatApiTest::TearDownTestCase()
58 {
59 }
60 
61 /*
62  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0100
63  * @tc.name   : FchownatFileSuccess_0001
64  * @tc.desc   : fchownat change specify path file owner id and group id success.
65  * @tc.size   : MediumTest
66  * @tc.type   : Function
67  * @tc.level  : Level 1
68  */
HWTEST_F(FchownatApiTest, FchownatFileSuccess_0001, Function | MediumTest | Level1)69 HWTEST_F(FchownatApiTest, FchownatFileSuccess_0001, Function | MediumTest | Level1)
70 {
71     int ret = -1;
72     struct stat stat1;
73     struct stat stat2;
74 
75     int dirfd = open(TEST_FILE_PATH, O_RDONLY | O_DIRECTORY);
76     EXPECT_TRUE(dirfd > 0);
77 
78     int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0755);
79     EXPECT_TRUE(fd > 0);
80     ret = fstat(fd, &stat1);
81     EXPECT_EQ(ret, 0);
82     uid_t uid = stat1.st_uid + 1;
83     gid_t gid = stat1.st_gid + 1;
84 
85     ret = fchownat(dirfd, TEST_FILE_NAME, uid, gid, 0);
86     EXPECT_EQ(ret, 0);
87     ret = fstat(fd, &stat2);
88     EXPECT_EQ(stat2.st_uid, uid);
89     EXPECT_EQ(stat2.st_gid, gid);
90 
91     close(dirfd);
92     close(fd);
93     remove(TEST_FILE);
94 }
95 
96 /*
97  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0200
98  * @tc.name   : FchownatAT_FDCWDTestSuccess_0002
99  * @tc.desc   : fchownat change current path file owner id and group id by AT_FDCWD success.
100  * @tc.size   : MediumTest
101  * @tc.type   : Function
102  * @tc.level  : Level 1
103  */
HWTEST_F(FchownatApiTest, FchownatAT_FDCWDTestSuccess_0002, Function | MediumTest | Level1)104 HWTEST_F(FchownatApiTest, FchownatAT_FDCWDTestSuccess_0002, Function | MediumTest | Level1)
105 {
106     int ret = -1;
107     char path[PATH_MAX_LEN];
108     struct stat stat1;
109     struct stat stat2;
110     int fd = 0;
111 
112     char *dir = getcwd(path, sizeof(path));
113     EXPECT_NE(dir, nullptr);
114     ret = chdir(TEST_FILE_PATH);
115     EXPECT_EQ(ret, 0);
116     if (access(TEST_FILE_NAME, F_OK) == -1) {
117         fd = open(TEST_FILE_NAME, O_RDWR | O_CREAT, MODE_0644);
118     }
119 
120     ret = fstat(fd, &stat1);
121     EXPECT_EQ(ret, 0);
122     uid_t uid = stat1.st_uid + 1;
123     gid_t gid = stat1.st_gid + 1;
124 
125     ret = fchownat(AT_FDCWD, TEST_FILE_NAME, uid, gid, 0);
126     EXPECT_EQ(ret, 0);
127     ret = fstat(fd, &stat2);
128     EXPECT_EQ(stat2.st_uid, uid);
129     EXPECT_EQ(stat2.st_gid, gid);
130 
131     chdir(path);
132     close(fd);
133     remove(TEST_FILE);
134 }
135 
136 /*
137  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0300
138  * @tc.name   : FchownatInvalidFdFail_0003
139  * @tc.desc   : fchownat change invalid file owner id and group id fail, errno EBADF.
140  * @tc.size   : MediumTest
141  * @tc.type   : Function
142  * @tc.level  : Level 2
143  */
HWTEST_F(FchownatApiTest, FchownatInvalidFdFail_0003, Function | MediumTest | Level2)144 HWTEST_F(FchownatApiTest, FchownatInvalidFdFail_0003, Function | MediumTest | Level2)
145 {
146     int invalidFd = -1;
147     errno = 0;
148     int ret = fchownat(invalidFd, TEST_FILE_NAME, 1, 1, 0);
149     EXPECT_NE(ret, 0);
150     EXPECT_EQ(errno, EBADF);
151 }
152 
153 /*
154  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0400
155  * @tc.name   : FchownatLinkFileTestSuccess_0004
156  * @tc.desc   : fchownat change file owner id and group id by file link success.
157  * @tc.size   : MediumTest
158  * @tc.type   : Function
159  * @tc.level  : Level 1
160  */
HWTEST_F(FchownatApiTest, FchownatLinkFileTestSuccess_0004, Function | MediumTest | Level1)161 HWTEST_F(FchownatApiTest, FchownatLinkFileTestSuccess_0004, Function | MediumTest | Level1)
162 {
163     int ret = -1;
164     struct stat stat1;
165     struct stat stat2;
166     char path[PATH_MAX_LEN];
167     char *dir = getcwd(path, sizeof(path));
168     EXPECT_NE(dir, nullptr);
169     ret = chdir(TEST_FILE_PATH);
170     EXPECT_EQ(ret, 0);
171 
172     int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0755);
173     EXPECT_TRUE(fd > 0);
174     ret = fstat(fd, &stat1);
175     EXPECT_EQ(ret, 0);
176     uid_t uid = stat1.st_uid + 1;
177     gid_t gid = stat1.st_gid + 1;
178 
179     ret = symlink(TEST_FILE_NAME, SYMBOL_LINK_NAME);
180     EXPECT_EQ(ret, 0);
181 
182     ret = fchownat(AT_FDCWD, SYMBOL_LINK_NAME, uid, gid, 0);
183     EXPECT_EQ(ret, 0);
184     ret = fstat(fd, &stat2);
185     EXPECT_EQ(ret, 0);
186     EXPECT_EQ(stat2.st_uid, uid);
187     EXPECT_EQ(stat2.st_gid, gid);
188 
189     unlink(TEST_FILE_NAME);
190     close(fd);
191     remove(TEST_FILE);
192     remove(SYMBOL_LINK_NAME);
193     chdir(path);
194 }
195 
196 /*
197  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0500
198  * @tc.name   : FchownatAT_SYMLINK_NOFOLLOWTestSuccess_0005
199  * @tc.desc   : fchownat change owner id and group id of file link itself success.
200  * @tc.size   : MediumTest
201  * @tc.type   : Function
202  * @tc.level  : Level 1
203  */
HWTEST_F(FchownatApiTest, FchownatAT_SYMLINK_NOFOLLOWTestSuccess_0005, Function | MediumTest | Level1)204 HWTEST_F(FchownatApiTest, FchownatAT_SYMLINK_NOFOLLOWTestSuccess_0005, Function | MediumTest | Level1)
205 {
206     int ret = -1;
207     struct stat stat1;
208     struct stat stat2;
209     char path[PATH_MAX_LEN];
210     char *dir = getcwd(path, sizeof(path));
211     EXPECT_NE(dir, nullptr);
212     ret = chdir(TEST_FILE_PATH);
213     EXPECT_EQ(ret, 0);
214 
215     int fd = open(TEST_FILE_NAME, O_RDWR | O_CREAT, MODE_0644);
216     EXPECT_TRUE(fd > 0);
217     ret = symlink(TEST_FILE_NAME, SYMBOL_LINK_NAME);
218     EXPECT_EQ(ret, 0);
219 
220     ret = fstat(fd, &stat1);
221     EXPECT_EQ(ret, 0);
222     uid_t uid = stat1.st_uid + 1;
223     gid_t gid = stat1.st_gid + 1;
224 
225     ret = fchownat(AT_FDCWD, SYMBOL_LINK_NAME, uid, gid, AT_SYMLINK_NOFOLLOW);
226     EXPECT_EQ(ret, 0);
227     ret = fstat(fd, &stat2);
228     EXPECT_EQ(ret, 0);
229     EXPECT_NE(stat2.st_uid, uid);
230     EXPECT_NE(stat2.st_gid, gid);
231 
232     unlink(TEST_FILE_NAME);
233     close(fd);
234     remove(TEST_FILE);
235     remove(SYMBOL_LINK_NAME);
236     chdir(path);
237 }
238 
239 /*
240  * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0600
241  * @tc.name   : FchownatAT_EMPTY_PATHTestSuccess_0006
242  * @tc.desc   : fchownat change current path file owner id and group id by AT_EMPTY_PATH success.
243  * @tc.size   : MediumTest
244  * @tc.type   : Function
245  * @tc.level  : Level 1
246  */
HWTEST_F(FchownatApiTest, FchownatAT_EMPTY_PATHTestSuccess_0006, Function | MediumTest | Level1)247 HWTEST_F(FchownatApiTest, FchownatAT_EMPTY_PATHTestSuccess_0006, Function | MediumTest | Level1)
248 {
249     int ret = -1;
250     struct stat stat1;
251 
252     int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0644);
253     EXPECT_TRUE(fd > 0);
254 
255     ret = fstat(fd, &stat1);
256     EXPECT_EQ(ret, 0);
257     uid_t uid = stat1.st_uid + 1;
258     gid_t gid = stat1.st_gid + 1;
259 
260     ret = fchownat(fd, "", uid, gid, AT_EMPTY_PATH);
261     EXPECT_EQ(ret, 0);
262 
263     close(fd);
264     remove(TEST_FILE);
265 }
266