xref: /aosp_15_r20/trusty/kernel/app/usercopytest/usercopytest.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (c) 2015, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker  * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker  * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker  * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker  * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker  * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker  * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker  *
12*344aa361SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker  *
15*344aa361SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker  */
23*344aa361SAndroid Build Coastguard Worker 
24*344aa361SAndroid Build Coastguard Worker #include <assert.h>
25*344aa361SAndroid Build Coastguard Worker #include <err.h>
26*344aa361SAndroid Build Coastguard Worker #include <kernel/usercopy.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
28*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
29*344aa361SAndroid Build Coastguard Worker #include <stdio.h>
30*344aa361SAndroid Build Coastguard Worker #include <string.h>
31*344aa361SAndroid Build Coastguard Worker #include <trusty/string.h>
32*344aa361SAndroid Build Coastguard Worker #ifdef ARCH_ARM64
33*344aa361SAndroid Build Coastguard Worker #include <arch/safecopy.h>
34*344aa361SAndroid Build Coastguard Worker #endif
35*344aa361SAndroid Build Coastguard Worker 
36*344aa361SAndroid Build Coastguard Worker #define PORT_NAME "com.android.kernel.usercopy-unittest"
37*344aa361SAndroid Build Coastguard Worker 
38*344aa361SAndroid Build Coastguard Worker #define TEST_BUF_SIZE (16)
39*344aa361SAndroid Build Coastguard Worker #define TEST_BUF1_SIZE (TEST_BUF_SIZE / 2)
40*344aa361SAndroid Build Coastguard Worker #define TEST_BUF2_SIZE (TEST_BUF_SIZE - TEST_BUF1_SIZE)
41*344aa361SAndroid Build Coastguard Worker #define TEST_BUF_COPY_START (1)
42*344aa361SAndroid Build Coastguard Worker #define TEST_BUF_COPY_SIZE (TEST_BUF_SIZE - TEST_BUF_COPY_START - 1)
43*344aa361SAndroid Build Coastguard Worker #define TEST_BUF1_COPY_SIZE (TEST_BUF1_SIZE - TEST_BUF_COPY_START)
44*344aa361SAndroid Build Coastguard Worker #define TEST_BUF2_COPY_SIZE (TEST_BUF_COPY_SIZE - TEST_BUF1_COPY_SIZE)
45*344aa361SAndroid Build Coastguard Worker #define TEST_BUF_COPY_LAST (TEST_BUF_SIZE - 1 - 1)
46*344aa361SAndroid Build Coastguard Worker #define TEST_BUF2_COPY_LAST (TEST_BUF_COPY_LAST - TEST_BUF1_SIZE)
47*344aa361SAndroid Build Coastguard Worker 
48*344aa361SAndroid Build Coastguard Worker #define SRC_DATA (0x22)
49*344aa361SAndroid Build Coastguard Worker #define DEST_DATA (0x11)
50*344aa361SAndroid Build Coastguard Worker 
51*344aa361SAndroid Build Coastguard Worker #define FLAGS_NO_PAGE (ARCH_MMU_FLAG_INVALID)
52*344aa361SAndroid Build Coastguard Worker #define FLAGS_NO_USER (0u)
53*344aa361SAndroid Build Coastguard Worker #define FLAGS_RO_USER (ARCH_MMU_FLAG_PERM_USER | ARCH_MMU_FLAG_PERM_RO)
54*344aa361SAndroid Build Coastguard Worker #define FLAGS_RW_USER (ARCH_MMU_FLAG_PERM_USER)
55*344aa361SAndroid Build Coastguard Worker 
56*344aa361SAndroid Build Coastguard Worker #define STACK_ADDR_IDX (0)
57*344aa361SAndroid Build Coastguard Worker #define HEAP_ADDR_IDX (1)
58*344aa361SAndroid Build Coastguard Worker #define GLOBAL_ADDR_IDX (2)
59*344aa361SAndroid Build Coastguard Worker 
60*344aa361SAndroid Build Coastguard Worker #define START_PAGE_ADDR ((void*)(PAGE_SIZE * 0x10))
61*344aa361SAndroid Build Coastguard Worker #define TEST_BUF_ADDR \
62*344aa361SAndroid Build Coastguard Worker     ((user_addr_t)((uintptr_t)(START_PAGE_ADDR + PAGE_SIZE - TEST_BUF1_SIZE)))
63*344aa361SAndroid Build Coastguard Worker 
get_addr_param(void)64*344aa361SAndroid Build Coastguard Worker static inline user_addr_t get_addr_param(void) {
65*344aa361SAndroid Build Coastguard Worker     const void* const* param_arr = GetParam();
66*344aa361SAndroid Build Coastguard Worker     const user_addr_t* addr = param_arr[0];
67*344aa361SAndroid Build Coastguard Worker     return *addr;
68*344aa361SAndroid Build Coastguard Worker }
69*344aa361SAndroid Build Coastguard Worker 
get_start_flags_param(void)70*344aa361SAndroid Build Coastguard Worker static inline uint32_t get_start_flags_param(void) {
71*344aa361SAndroid Build Coastguard Worker     const void* const* param_arr = GetParam();
72*344aa361SAndroid Build Coastguard Worker     const uint32_t* start_flags = param_arr[1];
73*344aa361SAndroid Build Coastguard Worker     return *start_flags;
74*344aa361SAndroid Build Coastguard Worker }
75*344aa361SAndroid Build Coastguard Worker 
get_end_flags_param(void)76*344aa361SAndroid Build Coastguard Worker static inline uint32_t get_end_flags_param(void) {
77*344aa361SAndroid Build Coastguard Worker     const void* const* param_arr = GetParam();
78*344aa361SAndroid Build Coastguard Worker     const uint32_t* end_flags = param_arr[2];
79*344aa361SAndroid Build Coastguard Worker     return *end_flags;
80*344aa361SAndroid Build Coastguard Worker }
81*344aa361SAndroid Build Coastguard Worker 
checkbuf(const char * buf,char c,size_t size)82*344aa361SAndroid Build Coastguard Worker static int checkbuf(const char* buf, char c, size_t size) {
83*344aa361SAndroid Build Coastguard Worker     int error_count = 0;
84*344aa361SAndroid Build Coastguard Worker     for (size_t i = 0; i < size; i++) {
85*344aa361SAndroid Build Coastguard Worker         if (buf[i] != c) {
86*344aa361SAndroid Build Coastguard Worker             error_count++;
87*344aa361SAndroid Build Coastguard Worker         }
88*344aa361SAndroid Build Coastguard Worker     }
89*344aa361SAndroid Build Coastguard Worker     return error_count;
90*344aa361SAndroid Build Coastguard Worker }
91*344aa361SAndroid Build Coastguard Worker 
usercopy_test_init_buf(char * kbuf1,char * kbuf2,uint8_t val,int null_offset)92*344aa361SAndroid Build Coastguard Worker static void usercopy_test_init_buf(char* kbuf1,
93*344aa361SAndroid Build Coastguard Worker                                    char* kbuf2,
94*344aa361SAndroid Build Coastguard Worker                                    uint8_t val,
95*344aa361SAndroid Build Coastguard Worker                                    int null_offset) {
96*344aa361SAndroid Build Coastguard Worker     if (kbuf1) {
97*344aa361SAndroid Build Coastguard Worker         memset(kbuf1, val, TEST_BUF1_SIZE);
98*344aa361SAndroid Build Coastguard Worker         if (null_offset >= 0 && null_offset < TEST_BUF1_SIZE) {
99*344aa361SAndroid Build Coastguard Worker             kbuf1[null_offset] = '\0';
100*344aa361SAndroid Build Coastguard Worker         }
101*344aa361SAndroid Build Coastguard Worker     }
102*344aa361SAndroid Build Coastguard Worker     if (kbuf2) {
103*344aa361SAndroid Build Coastguard Worker         memset(kbuf2, val, TEST_BUF2_SIZE);
104*344aa361SAndroid Build Coastguard Worker         if (null_offset >= TEST_BUF1_SIZE && null_offset < TEST_BUF_SIZE) {
105*344aa361SAndroid Build Coastguard Worker             kbuf2[null_offset - TEST_BUF1_SIZE] = '\0';
106*344aa361SAndroid Build Coastguard Worker         }
107*344aa361SAndroid Build Coastguard Worker     }
108*344aa361SAndroid Build Coastguard Worker }
109*344aa361SAndroid Build Coastguard Worker 
110*344aa361SAndroid Build Coastguard Worker typedef struct {
111*344aa361SAndroid Build Coastguard Worker     struct vmm_aspace* aspace;
112*344aa361SAndroid Build Coastguard Worker } usercopytest_t;
113*344aa361SAndroid Build Coastguard Worker 
TEST_F_SETUP(usercopytest)114*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(usercopytest) {
115*344aa361SAndroid Build Coastguard Worker     int ret;
116*344aa361SAndroid Build Coastguard Worker     void* addr = START_PAGE_ADDR;
117*344aa361SAndroid Build Coastguard Worker     uint32_t start_flags = get_start_flags_param();
118*344aa361SAndroid Build Coastguard Worker     uint32_t end_flags = get_end_flags_param();
119*344aa361SAndroid Build Coastguard Worker 
120*344aa361SAndroid Build Coastguard Worker     _state->aspace = NULL;
121*344aa361SAndroid Build Coastguard Worker 
122*344aa361SAndroid Build Coastguard Worker     ret = vmm_create_aspace(&_state->aspace, "usercopy_test", 0);
123*344aa361SAndroid Build Coastguard Worker     ASSERT_EQ(NO_ERROR, ret);
124*344aa361SAndroid Build Coastguard Worker 
125*344aa361SAndroid Build Coastguard Worker     if (start_flags != FLAGS_NO_PAGE) {
126*344aa361SAndroid Build Coastguard Worker         ret = vmm_alloc(_state->aspace, "start-page", PAGE_SIZE, &addr, 0,
127*344aa361SAndroid Build Coastguard Worker                         VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
128*344aa361SAndroid Build Coastguard Worker                         start_flags | ARCH_MMU_FLAG_PERM_NO_EXECUTE);
129*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(NO_ERROR, ret);
130*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(START_PAGE_ADDR, addr);
131*344aa361SAndroid Build Coastguard Worker     }
132*344aa361SAndroid Build Coastguard Worker 
133*344aa361SAndroid Build Coastguard Worker     addr += PAGE_SIZE;
134*344aa361SAndroid Build Coastguard Worker 
135*344aa361SAndroid Build Coastguard Worker     if (end_flags != FLAGS_NO_PAGE) {
136*344aa361SAndroid Build Coastguard Worker         ret = vmm_alloc(_state->aspace, "end-page", PAGE_SIZE, &addr, 0,
137*344aa361SAndroid Build Coastguard Worker                         VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD,
138*344aa361SAndroid Build Coastguard Worker                         end_flags | ARCH_MMU_FLAG_PERM_NO_EXECUTE);
139*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(NO_ERROR, ret);
140*344aa361SAndroid Build Coastguard Worker         ASSERT_EQ(START_PAGE_ADDR + PAGE_SIZE, addr);
141*344aa361SAndroid Build Coastguard Worker     }
142*344aa361SAndroid Build Coastguard Worker 
143*344aa361SAndroid Build Coastguard Worker     vmm_set_active_aspace(_state->aspace);
144*344aa361SAndroid Build Coastguard Worker 
145*344aa361SAndroid Build Coastguard Worker test_abort:
146*344aa361SAndroid Build Coastguard Worker     return;
147*344aa361SAndroid Build Coastguard Worker }
148*344aa361SAndroid Build Coastguard Worker 
TEST_F_TEARDOWN(usercopytest)149*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(usercopytest) {
150*344aa361SAndroid Build Coastguard Worker     vmm_set_active_aspace(NULL);
151*344aa361SAndroid Build Coastguard Worker 
152*344aa361SAndroid Build Coastguard Worker     if (_state->aspace) {
153*344aa361SAndroid Build Coastguard Worker         vmm_free_aspace(_state->aspace);
154*344aa361SAndroid Build Coastguard Worker     }
155*344aa361SAndroid Build Coastguard Worker }
156*344aa361SAndroid Build Coastguard Worker 
TEST_P(usercopytest,copy_to_user)157*344aa361SAndroid Build Coastguard Worker TEST_P(usercopytest, copy_to_user) {
158*344aa361SAndroid Build Coastguard Worker     user_addr_t addr = get_addr_param();
159*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_start = get_start_flags_param();
160*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_end = get_end_flags_param();
161*344aa361SAndroid Build Coastguard Worker     int ret;
162*344aa361SAndroid Build Coastguard Worker     char src_buf[TEST_BUF_SIZE];
163*344aa361SAndroid Build Coastguard Worker     char* dest_kbuf1;
164*344aa361SAndroid Build Coastguard Worker     char* dest_kbuf2;
165*344aa361SAndroid Build Coastguard Worker     char expect1;
166*344aa361SAndroid Build Coastguard Worker     char expect2;
167*344aa361SAndroid Build Coastguard Worker 
168*344aa361SAndroid Build Coastguard Worker     dest_kbuf1 = paddr_to_kvaddr(vaddr_to_paddr((void*)(uintptr_t)addr));
169*344aa361SAndroid Build Coastguard Worker     dest_kbuf2 = paddr_to_kvaddr(
170*344aa361SAndroid Build Coastguard Worker             vaddr_to_paddr((void*)(uintptr_t)addr + TEST_BUF1_SIZE));
171*344aa361SAndroid Build Coastguard Worker 
172*344aa361SAndroid Build Coastguard Worker     /* dest buffs should be NULL iff their flags are FLAGS_NO_PAGE */
173*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((dest_kbuf1 == NULL), (arch_mmu_flags_start == FLAGS_NO_PAGE));
174*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((dest_kbuf2 == NULL), (arch_mmu_flags_end == FLAGS_NO_PAGE));
175*344aa361SAndroid Build Coastguard Worker 
176*344aa361SAndroid Build Coastguard Worker     usercopy_test_init_buf(dest_kbuf1, dest_kbuf2, DEST_DATA, -1);
177*344aa361SAndroid Build Coastguard Worker     memset(src_buf, SRC_DATA, sizeof(src_buf));
178*344aa361SAndroid Build Coastguard Worker 
179*344aa361SAndroid Build Coastguard Worker     /* Zero-length copy should always succeed */
180*344aa361SAndroid Build Coastguard Worker     ret = copy_to_user(addr + TEST_BUF_COPY_START, NULL, 0);
181*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, ret);
182*344aa361SAndroid Build Coastguard Worker 
183*344aa361SAndroid Build Coastguard Worker     /* Dest buffer should be untouched after zero-length copy */
184*344aa361SAndroid Build Coastguard Worker     if (dest_kbuf1) {
185*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(dest_kbuf1, DEST_DATA, TEST_BUF1_SIZE));
186*344aa361SAndroid Build Coastguard Worker     }
187*344aa361SAndroid Build Coastguard Worker     if (dest_kbuf2) {
188*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(dest_kbuf2, DEST_DATA, TEST_BUF2_SIZE));
189*344aa361SAndroid Build Coastguard Worker     }
190*344aa361SAndroid Build Coastguard Worker 
191*344aa361SAndroid Build Coastguard Worker     /* Perform non-zero length copy */
192*344aa361SAndroid Build Coastguard Worker     ret = copy_to_user(addr + TEST_BUF_COPY_START,
193*344aa361SAndroid Build Coastguard Worker                        src_buf + TEST_BUF_COPY_START, TEST_BUF_COPY_SIZE);
194*344aa361SAndroid Build Coastguard Worker 
195*344aa361SAndroid Build Coastguard Worker     /*
196*344aa361SAndroid Build Coastguard Worker      * If both pages are writeable copy_to_user should succeed otherwise it
197*344aa361SAndroid Build Coastguard Worker      * should return ERR_FAULT.
198*344aa361SAndroid Build Coastguard Worker      */
199*344aa361SAndroid Build Coastguard Worker     if (arch_mmu_flags_start == ARCH_MMU_FLAG_PERM_USER &&
200*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_end == ARCH_MMU_FLAG_PERM_USER) {
201*344aa361SAndroid Build Coastguard Worker         /*
202*344aa361SAndroid Build Coastguard Worker          * If both pages are writeable from user-space copy_to_user should
203*344aa361SAndroid Build Coastguard Worker          * return success and every byte should be copied to dest_buf.
204*344aa361SAndroid Build Coastguard Worker          */
205*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, ret);
206*344aa361SAndroid Build Coastguard Worker         expect1 = SRC_DATA;
207*344aa361SAndroid Build Coastguard Worker         expect2 = SRC_DATA;
208*344aa361SAndroid Build Coastguard Worker     } else {
209*344aa361SAndroid Build Coastguard Worker         /*
210*344aa361SAndroid Build Coastguard Worker          * If one of the pages is not writeable from user-space copy_to_user
211*344aa361SAndroid Build Coastguard Worker          * should return ERR_FAULT. If only the first page is writeable everying
212*344aa361SAndroid Build Coastguard Worker          * should be copied in the first page or nothing should be copied in the
213*344aa361SAndroid Build Coastguard Worker          * first page. If the first page is not writeable, nothing should be
214*344aa361SAndroid Build Coastguard Worker          * copied to either page. If the second page is not writeable, no data
215*344aa361SAndroid Build Coastguard Worker          * should be copied to it, even if the first page was written to.
216*344aa361SAndroid Build Coastguard Worker          */
217*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(ERR_FAULT, ret);
218*344aa361SAndroid Build Coastguard Worker         if (arch_mmu_flags_start == ARCH_MMU_FLAG_PERM_USER &&
219*344aa361SAndroid Build Coastguard Worker             dest_kbuf1[TEST_BUF_COPY_START] == SRC_DATA) {
220*344aa361SAndroid Build Coastguard Worker             expect1 = SRC_DATA;
221*344aa361SAndroid Build Coastguard Worker         } else {
222*344aa361SAndroid Build Coastguard Worker             expect1 = DEST_DATA;
223*344aa361SAndroid Build Coastguard Worker         }
224*344aa361SAndroid Build Coastguard Worker         expect2 = DEST_DATA;
225*344aa361SAndroid Build Coastguard Worker     }
226*344aa361SAndroid Build Coastguard Worker 
227*344aa361SAndroid Build Coastguard Worker     /* copy_to_user should not modify src_buf at all */
228*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(src_buf, SRC_DATA, TEST_BUF_SIZE));
229*344aa361SAndroid Build Coastguard Worker 
230*344aa361SAndroid Build Coastguard Worker     if (dest_kbuf1) {
231*344aa361SAndroid Build Coastguard Worker         /* Dest byte before copied region should be untouched */
232*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(DEST_DATA, dest_kbuf1[0]);
233*344aa361SAndroid Build Coastguard Worker 
234*344aa361SAndroid Build Coastguard Worker         /* Check that copied region match expected value we selected above */
235*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(dest_kbuf1 + TEST_BUF_COPY_START, expect1,
236*344aa361SAndroid Build Coastguard Worker                               TEST_BUF1_COPY_SIZE));
237*344aa361SAndroid Build Coastguard Worker     }
238*344aa361SAndroid Build Coastguard Worker 
239*344aa361SAndroid Build Coastguard Worker     if (dest_kbuf2) {
240*344aa361SAndroid Build Coastguard Worker         /* Check that copied region match expected value we selected above */
241*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(dest_kbuf2, expect2, TEST_BUF2_COPY_SIZE));
242*344aa361SAndroid Build Coastguard Worker 
243*344aa361SAndroid Build Coastguard Worker         /* Dest byte after copied region should be untouched */
244*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(DEST_DATA, dest_kbuf2[TEST_BUF2_SIZE - 1]);
245*344aa361SAndroid Build Coastguard Worker     }
246*344aa361SAndroid Build Coastguard Worker }
247*344aa361SAndroid Build Coastguard Worker 
TEST_P(usercopytest,copy_from_user)248*344aa361SAndroid Build Coastguard Worker TEST_P(usercopytest, copy_from_user) {
249*344aa361SAndroid Build Coastguard Worker     user_addr_t addr = get_addr_param();
250*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_start = get_start_flags_param();
251*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_end = get_end_flags_param();
252*344aa361SAndroid Build Coastguard Worker     int ret;
253*344aa361SAndroid Build Coastguard Worker     char dest_buf[TEST_BUF_SIZE];
254*344aa361SAndroid Build Coastguard Worker     char* src_kbuf1;
255*344aa361SAndroid Build Coastguard Worker     char* src_kbuf2;
256*344aa361SAndroid Build Coastguard Worker     char expect1;
257*344aa361SAndroid Build Coastguard Worker     char expect2;
258*344aa361SAndroid Build Coastguard Worker 
259*344aa361SAndroid Build Coastguard Worker     memset(dest_buf, DEST_DATA, sizeof(dest_buf));
260*344aa361SAndroid Build Coastguard Worker     src_kbuf1 = paddr_to_kvaddr(vaddr_to_paddr((void*)(uintptr_t)addr));
261*344aa361SAndroid Build Coastguard Worker     src_kbuf2 = paddr_to_kvaddr(
262*344aa361SAndroid Build Coastguard Worker             vaddr_to_paddr((void*)(uintptr_t)addr + TEST_BUF1_SIZE));
263*344aa361SAndroid Build Coastguard Worker 
264*344aa361SAndroid Build Coastguard Worker     /* src buffs should be NULL iff their flags are FLAGS_NO_PAGE */
265*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf1 == NULL), (arch_mmu_flags_start == FLAGS_NO_PAGE));
266*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf2 == NULL), (arch_mmu_flags_end == FLAGS_NO_PAGE));
267*344aa361SAndroid Build Coastguard Worker 
268*344aa361SAndroid Build Coastguard Worker     usercopy_test_init_buf(src_kbuf1, src_kbuf2, SRC_DATA, -1);
269*344aa361SAndroid Build Coastguard Worker 
270*344aa361SAndroid Build Coastguard Worker     /* Zero-length copy should always succeed */
271*344aa361SAndroid Build Coastguard Worker     ret = copy_from_user(NULL, addr + TEST_BUF_COPY_START, 0);
272*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, ret);
273*344aa361SAndroid Build Coastguard Worker 
274*344aa361SAndroid Build Coastguard Worker     /* Dest buffer should be untouched after zero-length copy */
275*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf, DEST_DATA, TEST_BUF_SIZE));
276*344aa361SAndroid Build Coastguard Worker 
277*344aa361SAndroid Build Coastguard Worker     /* Perform non-zero length copy */
278*344aa361SAndroid Build Coastguard Worker     ret = copy_from_user(dest_buf + TEST_BUF_COPY_START,
279*344aa361SAndroid Build Coastguard Worker                          addr + TEST_BUF_COPY_START, TEST_BUF_COPY_SIZE);
280*344aa361SAndroid Build Coastguard Worker     if (arch_mmu_flags_start & arch_mmu_flags_end & ARCH_MMU_FLAG_PERM_USER) {
281*344aa361SAndroid Build Coastguard Worker         /*
282*344aa361SAndroid Build Coastguard Worker          * If both pages are readable from user-space copy_from_user should
283*344aa361SAndroid Build Coastguard Worker          * return success and every byte should be copied to dest_buf.
284*344aa361SAndroid Build Coastguard Worker          */
285*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, ret);
286*344aa361SAndroid Build Coastguard Worker         expect1 = SRC_DATA;
287*344aa361SAndroid Build Coastguard Worker         expect2 = SRC_DATA;
288*344aa361SAndroid Build Coastguard Worker     } else {
289*344aa361SAndroid Build Coastguard Worker         /*
290*344aa361SAndroid Build Coastguard Worker          * If one of the pages is not readable from user-space copy_from_user
291*344aa361SAndroid Build Coastguard Worker          * should return ERR_FAULT, and the parts of dest_buf that could not be
292*344aa361SAndroid Build Coastguard Worker          * copied into should be set to 0.
293*344aa361SAndroid Build Coastguard Worker          * The destination kernel buffer should always be written so
294*344aa361SAndroid Build Coastguard Worker          * potentially uninitialized kernel data does not leak.
295*344aa361SAndroid Build Coastguard Worker          */
296*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(ERR_FAULT, ret);
297*344aa361SAndroid Build Coastguard Worker         if (!(arch_mmu_flags_start & ARCH_MMU_FLAG_PERM_USER) ||
298*344aa361SAndroid Build Coastguard Worker             !dest_buf[TEST_BUF_COPY_START]) {
299*344aa361SAndroid Build Coastguard Worker             expect1 = 0;
300*344aa361SAndroid Build Coastguard Worker         } else {
301*344aa361SAndroid Build Coastguard Worker             expect1 = SRC_DATA;
302*344aa361SAndroid Build Coastguard Worker         }
303*344aa361SAndroid Build Coastguard Worker         expect2 = 0;
304*344aa361SAndroid Build Coastguard Worker     }
305*344aa361SAndroid Build Coastguard Worker 
306*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf + TEST_BUF_COPY_START, expect1,
307*344aa361SAndroid Build Coastguard Worker                           TEST_BUF1_COPY_SIZE));
308*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf + TEST_BUF1_SIZE, expect2,
309*344aa361SAndroid Build Coastguard Worker                           TEST_BUF2_COPY_SIZE));
310*344aa361SAndroid Build Coastguard Worker 
311*344aa361SAndroid Build Coastguard Worker     /* Dest bytes before and after copied region should be untouched */
312*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[0]);
313*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[TEST_BUF_SIZE - 1]);
314*344aa361SAndroid Build Coastguard Worker 
315*344aa361SAndroid Build Coastguard Worker     /* Src buffer should not be modified */
316*344aa361SAndroid Build Coastguard Worker     if (src_kbuf1) {
317*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(src_kbuf1, SRC_DATA, TEST_BUF1_SIZE));
318*344aa361SAndroid Build Coastguard Worker     }
319*344aa361SAndroid Build Coastguard Worker     if (src_kbuf2) {
320*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(src_kbuf2, SRC_DATA, TEST_BUF2_SIZE));
321*344aa361SAndroid Build Coastguard Worker     }
322*344aa361SAndroid Build Coastguard Worker }
323*344aa361SAndroid Build Coastguard Worker 
324*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
325*344aa361SAndroid Build Coastguard Worker #define ENABLED_ON_ARM64_NAME(name) name
326*344aa361SAndroid Build Coastguard Worker #else
327*344aa361SAndroid Build Coastguard Worker #define ENABLED_ON_ARM64_NAME(name) DISABLED_##name
328*344aa361SAndroid Build Coastguard Worker #define copy_from_anywhere(dst, src, len) -1
329*344aa361SAndroid Build Coastguard Worker #endif
330*344aa361SAndroid Build Coastguard Worker 
TEST_P(usercopytest,ENABLED_ON_ARM64_NAME (copy_from_anywhere))331*344aa361SAndroid Build Coastguard Worker TEST_P(usercopytest, ENABLED_ON_ARM64_NAME(copy_from_anywhere)) {
332*344aa361SAndroid Build Coastguard Worker     user_addr_t addr = get_addr_param();
333*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_start = get_start_flags_param();
334*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_end = get_end_flags_param();
335*344aa361SAndroid Build Coastguard Worker     int ret;
336*344aa361SAndroid Build Coastguard Worker     char dest_buf[TEST_BUF_SIZE];
337*344aa361SAndroid Build Coastguard Worker     char* src_kbuf1;
338*344aa361SAndroid Build Coastguard Worker     char* src_kbuf2;
339*344aa361SAndroid Build Coastguard Worker     char expect1;
340*344aa361SAndroid Build Coastguard Worker     char expect2;
341*344aa361SAndroid Build Coastguard Worker 
342*344aa361SAndroid Build Coastguard Worker     memset(dest_buf, DEST_DATA, sizeof(dest_buf));
343*344aa361SAndroid Build Coastguard Worker     src_kbuf1 = paddr_to_kvaddr(vaddr_to_paddr((void*)(uintptr_t)addr));
344*344aa361SAndroid Build Coastguard Worker     src_kbuf2 = paddr_to_kvaddr(
345*344aa361SAndroid Build Coastguard Worker             vaddr_to_paddr((void*)(uintptr_t)addr + TEST_BUF1_SIZE));
346*344aa361SAndroid Build Coastguard Worker 
347*344aa361SAndroid Build Coastguard Worker     /* src buffs should be NULL iff their flags are FLAGS_NO_PAGE */
348*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf1 == NULL), (arch_mmu_flags_start == FLAGS_NO_PAGE));
349*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf2 == NULL), (arch_mmu_flags_end == FLAGS_NO_PAGE));
350*344aa361SAndroid Build Coastguard Worker 
351*344aa361SAndroid Build Coastguard Worker     usercopy_test_init_buf(src_kbuf1, src_kbuf2, SRC_DATA, -1);
352*344aa361SAndroid Build Coastguard Worker 
353*344aa361SAndroid Build Coastguard Worker     /* Zero-length copy should always succeed */
354*344aa361SAndroid Build Coastguard Worker     ret = copy_from_anywhere(NULL, addr + TEST_BUF_COPY_START, 0);
355*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, ret);
356*344aa361SAndroid Build Coastguard Worker 
357*344aa361SAndroid Build Coastguard Worker     /* Dest buffer should be untouched after zero-length copy */
358*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf, DEST_DATA, TEST_BUF_SIZE));
359*344aa361SAndroid Build Coastguard Worker 
360*344aa361SAndroid Build Coastguard Worker     /* Perform non-zero length copy */
361*344aa361SAndroid Build Coastguard Worker     ret = copy_from_anywhere(dest_buf + TEST_BUF_COPY_START,
362*344aa361SAndroid Build Coastguard Worker                              addr + TEST_BUF_COPY_START, TEST_BUF_COPY_SIZE);
363*344aa361SAndroid Build Coastguard Worker     if (arch_mmu_flags_start != FLAGS_NO_PAGE &&
364*344aa361SAndroid Build Coastguard Worker         arch_mmu_flags_end != FLAGS_NO_PAGE) {
365*344aa361SAndroid Build Coastguard Worker         /*
366*344aa361SAndroid Build Coastguard Worker          * If both pages are readable, copy_from_anywhere should return
367*344aa361SAndroid Build Coastguard Worker          * success and every byte should be copied to dest_buf.
368*344aa361SAndroid Build Coastguard Worker          */
369*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, ret);
370*344aa361SAndroid Build Coastguard Worker         expect1 = SRC_DATA;
371*344aa361SAndroid Build Coastguard Worker         expect2 = SRC_DATA;
372*344aa361SAndroid Build Coastguard Worker     } else {
373*344aa361SAndroid Build Coastguard Worker         /*
374*344aa361SAndroid Build Coastguard Worker          * If one of the pages is not readable copy_from_anywhere should
375*344aa361SAndroid Build Coastguard Worker          * return ERR_FAULT, and the parts of dest_buf that could not be
376*344aa361SAndroid Build Coastguard Worker          * copied into should be set to 0.
377*344aa361SAndroid Build Coastguard Worker          * The destination kernel buffer should always be written so
378*344aa361SAndroid Build Coastguard Worker          * potentially uninitialized kernel data does not leak.
379*344aa361SAndroid Build Coastguard Worker          */
380*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(ERR_FAULT, ret);
381*344aa361SAndroid Build Coastguard Worker         if (arch_mmu_flags_start == FLAGS_NO_PAGE) {
382*344aa361SAndroid Build Coastguard Worker             expect1 = 0;
383*344aa361SAndroid Build Coastguard Worker         } else {
384*344aa361SAndroid Build Coastguard Worker             expect1 = SRC_DATA;
385*344aa361SAndroid Build Coastguard Worker         }
386*344aa361SAndroid Build Coastguard Worker         expect2 = 0;
387*344aa361SAndroid Build Coastguard Worker     }
388*344aa361SAndroid Build Coastguard Worker 
389*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf + TEST_BUF_COPY_START, expect1,
390*344aa361SAndroid Build Coastguard Worker                           TEST_BUF1_COPY_SIZE));
391*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf + TEST_BUF1_SIZE, expect2,
392*344aa361SAndroid Build Coastguard Worker                           TEST_BUF2_COPY_SIZE));
393*344aa361SAndroid Build Coastguard Worker 
394*344aa361SAndroid Build Coastguard Worker     /* Dest bytes before and after copied region should be untouched */
395*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[0]);
396*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[TEST_BUF_SIZE - 1]);
397*344aa361SAndroid Build Coastguard Worker 
398*344aa361SAndroid Build Coastguard Worker     /* Src buffer should not be modified */
399*344aa361SAndroid Build Coastguard Worker     if (src_kbuf1) {
400*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(src_kbuf1, SRC_DATA, TEST_BUF1_SIZE));
401*344aa361SAndroid Build Coastguard Worker     }
402*344aa361SAndroid Build Coastguard Worker     if (src_kbuf2) {
403*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(0, checkbuf(src_kbuf2, SRC_DATA, TEST_BUF2_SIZE));
404*344aa361SAndroid Build Coastguard Worker     }
405*344aa361SAndroid Build Coastguard Worker }
406*344aa361SAndroid Build Coastguard Worker 
usercopy_test_strlcpy_from_user_inner(user_addr_t addr,uint arch_mmu_flags_start,uint arch_mmu_flags_end,int copy_size,int null_off)407*344aa361SAndroid Build Coastguard Worker static void usercopy_test_strlcpy_from_user_inner(user_addr_t addr,
408*344aa361SAndroid Build Coastguard Worker                                                   uint arch_mmu_flags_start,
409*344aa361SAndroid Build Coastguard Worker                                                   uint arch_mmu_flags_end,
410*344aa361SAndroid Build Coastguard Worker                                                   int copy_size,
411*344aa361SAndroid Build Coastguard Worker                                                   int null_off) {
412*344aa361SAndroid Build Coastguard Worker     int ret;
413*344aa361SAndroid Build Coastguard Worker     char dest_buf[TEST_BUF_SIZE];
414*344aa361SAndroid Build Coastguard Worker     char* src_kbuf1;
415*344aa361SAndroid Build Coastguard Worker     char* src_kbuf2;
416*344aa361SAndroid Build Coastguard Worker     size_t dest_len;
417*344aa361SAndroid Build Coastguard Worker     int copy_len = copy_size ? copy_size - 1 : 0;
418*344aa361SAndroid Build Coastguard Worker 
419*344aa361SAndroid Build Coastguard Worker     memset(dest_buf, DEST_DATA, sizeof(dest_buf));
420*344aa361SAndroid Build Coastguard Worker     src_kbuf1 = paddr_to_kvaddr(vaddr_to_paddr((void*)(uintptr_t)addr));
421*344aa361SAndroid Build Coastguard Worker     src_kbuf2 = paddr_to_kvaddr(
422*344aa361SAndroid Build Coastguard Worker             vaddr_to_paddr((void*)(uintptr_t)addr + TEST_BUF1_SIZE));
423*344aa361SAndroid Build Coastguard Worker 
424*344aa361SAndroid Build Coastguard Worker     /* src buffs should be NULL iff their flags are FLAGS_NO_PAGE */
425*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf1 == NULL), (arch_mmu_flags_start == FLAGS_NO_PAGE));
426*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ((src_kbuf2 == NULL), (arch_mmu_flags_end == FLAGS_NO_PAGE));
427*344aa361SAndroid Build Coastguard Worker 
428*344aa361SAndroid Build Coastguard Worker     usercopy_test_init_buf(src_kbuf1, src_kbuf2, SRC_DATA, null_off);
429*344aa361SAndroid Build Coastguard Worker 
430*344aa361SAndroid Build Coastguard Worker     ret = strlcpy_from_user(dest_buf + TEST_BUF_COPY_START,
431*344aa361SAndroid Build Coastguard Worker                             addr + TEST_BUF_COPY_START, copy_size);
432*344aa361SAndroid Build Coastguard Worker 
433*344aa361SAndroid Build Coastguard Worker     dest_len = strnlen(dest_buf + TEST_BUF_COPY_START, TEST_BUF_COPY_SIZE);
434*344aa361SAndroid Build Coastguard Worker     if (copy_size) {
435*344aa361SAndroid Build Coastguard Worker         /*
436*344aa361SAndroid Build Coastguard Worker          * Kernel buffer should always be null terminated.
437*344aa361SAndroid Build Coastguard Worker          */
438*344aa361SAndroid Build Coastguard Worker         EXPECT_NE(TEST_BUF_COPY_SIZE, dest_len, "  null_off=%d, copy_size=%d\n",
439*344aa361SAndroid Build Coastguard Worker                   null_off, copy_size);
440*344aa361SAndroid Build Coastguard Worker     } else {
441*344aa361SAndroid Build Coastguard Worker         /*
442*344aa361SAndroid Build Coastguard Worker          * If copy_size is 0, then kernel buffer will not be null terminated.
443*344aa361SAndroid Build Coastguard Worker          */
444*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(TEST_BUF_COPY_SIZE, dest_len, "  null_off=%d, copy_size=%d\n",
445*344aa361SAndroid Build Coastguard Worker                   null_off, copy_size);
446*344aa361SAndroid Build Coastguard Worker         dest_len = 0;
447*344aa361SAndroid Build Coastguard Worker     }
448*344aa361SAndroid Build Coastguard Worker 
449*344aa361SAndroid Build Coastguard Worker     /*
450*344aa361SAndroid Build Coastguard Worker      * If the string in dest_buf is not empty it should only contain data from
451*344aa361SAndroid Build Coastguard Worker      * the source string.
452*344aa361SAndroid Build Coastguard Worker      */
453*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(0, checkbuf(dest_buf + TEST_BUF_COPY_START, SRC_DATA, dest_len),
454*344aa361SAndroid Build Coastguard Worker               "  null_off=%d, copy_size=%d\n", null_off, copy_size);
455*344aa361SAndroid Build Coastguard Worker 
456*344aa361SAndroid Build Coastguard Worker     if ((arch_mmu_flags_start & ARCH_MMU_FLAG_PERM_USER) &&
457*344aa361SAndroid Build Coastguard Worker         ((arch_mmu_flags_end & ARCH_MMU_FLAG_PERM_USER) ||
458*344aa361SAndroid Build Coastguard Worker          null_off < TEST_BUF1_SIZE)) {
459*344aa361SAndroid Build Coastguard Worker         /*
460*344aa361SAndroid Build Coastguard Worker          * If the pages readable from user-space contain a 0 terminated string,
461*344aa361SAndroid Build Coastguard Worker          * strlcpy_from_user should return the length of that string and every
462*344aa361SAndroid Build Coastguard Worker          * byte up to the 0 terminator that fits in dest_buf should be copied
463*344aa361SAndroid Build Coastguard Worker          * there. dest_buf should always be 0 terminated.
464*344aa361SAndroid Build Coastguard Worker          */
465*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(null_off - TEST_BUF_COPY_START, ret,
466*344aa361SAndroid Build Coastguard Worker                   "  wrong strlen returned, null_off=%d, copy_size=%d\n",
467*344aa361SAndroid Build Coastguard Worker                   null_off, copy_size);
468*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(MIN(null_off - TEST_BUF_COPY_START, copy_len), dest_len,
469*344aa361SAndroid Build Coastguard Worker                   "  null_off=%d, copy_size=%d\n", null_off, copy_size);
470*344aa361SAndroid Build Coastguard Worker     } else {
471*344aa361SAndroid Build Coastguard Worker         /*
472*344aa361SAndroid Build Coastguard Worker          * If one of the pages is not readable from user-space strlcpy_from_user
473*344aa361SAndroid Build Coastguard Worker          * should return ERR_FAULT, and dest_buf should have a null terminator
474*344aa361SAndroid Build Coastguard Worker          * at the start of the faulting page or at the start of the string.
475*344aa361SAndroid Build Coastguard Worker          */
476*344aa361SAndroid Build Coastguard Worker         EXPECT_EQ(ERR_FAULT, ret, "  null_off=%d, copy_size=%d\n", null_off,
477*344aa361SAndroid Build Coastguard Worker                   copy_size);
478*344aa361SAndroid Build Coastguard Worker         if (!(arch_mmu_flags_start & ARCH_MMU_FLAG_PERM_USER)) {
479*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, dest_len, "  null_off=%d, copy_size=%d\n", null_off,
480*344aa361SAndroid Build Coastguard Worker                       copy_size);
481*344aa361SAndroid Build Coastguard Worker         } else if (dest_len) {
482*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(MIN(TEST_BUF1_COPY_SIZE, copy_len), dest_len,
483*344aa361SAndroid Build Coastguard Worker                       "  null_off=%d, copy_size=%d\n", null_off, copy_size);
484*344aa361SAndroid Build Coastguard Worker         }
485*344aa361SAndroid Build Coastguard Worker     }
486*344aa361SAndroid Build Coastguard Worker 
487*344aa361SAndroid Build Coastguard Worker     /* Src buffer should not be modified */
488*344aa361SAndroid Build Coastguard Worker     if (src_kbuf1) {
489*344aa361SAndroid Build Coastguard Worker         if (null_off < TEST_BUF1_SIZE) {
490*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf1, SRC_DATA, null_off));
491*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ('\0', src_kbuf1[null_off]);
492*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf1 + null_off + 1, SRC_DATA,
493*344aa361SAndroid Build Coastguard Worker                                   TEST_BUF1_SIZE - null_off - 1));
494*344aa361SAndroid Build Coastguard Worker         } else {
495*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf1, SRC_DATA, TEST_BUF1_SIZE));
496*344aa361SAndroid Build Coastguard Worker         }
497*344aa361SAndroid Build Coastguard Worker     }
498*344aa361SAndroid Build Coastguard Worker     if (src_kbuf2) {
499*344aa361SAndroid Build Coastguard Worker         if (null_off >= TEST_BUF1_SIZE) {
500*344aa361SAndroid Build Coastguard Worker             size_t null_off2 = null_off - TEST_BUF1_SIZE;
501*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf2, SRC_DATA, null_off2));
502*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ('\0', src_kbuf2[null_off2]);
503*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf2 + null_off2 + 1, SRC_DATA,
504*344aa361SAndroid Build Coastguard Worker                                   TEST_BUF2_SIZE - null_off2 - 1));
505*344aa361SAndroid Build Coastguard Worker         } else {
506*344aa361SAndroid Build Coastguard Worker             EXPECT_EQ(0, checkbuf(src_kbuf2, SRC_DATA, TEST_BUF2_SIZE));
507*344aa361SAndroid Build Coastguard Worker         }
508*344aa361SAndroid Build Coastguard Worker     }
509*344aa361SAndroid Build Coastguard Worker 
510*344aa361SAndroid Build Coastguard Worker     /* Dest bytes before and after copied region should be untouched */
511*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[0]);
512*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[TEST_BUF_COPY_START + copy_size]);
513*344aa361SAndroid Build Coastguard Worker     EXPECT_EQ(DEST_DATA, dest_buf[TEST_BUF_SIZE - 1]);
514*344aa361SAndroid Build Coastguard Worker }
515*344aa361SAndroid Build Coastguard Worker 
TEST_P(usercopytest,strlcpy_from_user)516*344aa361SAndroid Build Coastguard Worker TEST_P(usercopytest, strlcpy_from_user) {
517*344aa361SAndroid Build Coastguard Worker     user_addr_t addr = get_addr_param();
518*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_start = get_start_flags_param();
519*344aa361SAndroid Build Coastguard Worker     uint32_t arch_mmu_flags_end = get_end_flags_param();
520*344aa361SAndroid Build Coastguard Worker     size_t copy_sizes[] = {0, TEST_BUF1_COPY_SIZE, TEST_BUF_COPY_SIZE};
521*344aa361SAndroid Build Coastguard Worker     size_t copy_sizes_index;
522*344aa361SAndroid Build Coastguard Worker     int null_off;
523*344aa361SAndroid Build Coastguard Worker     int copy_size;
524*344aa361SAndroid Build Coastguard Worker 
525*344aa361SAndroid Build Coastguard Worker     for (copy_sizes_index = 0; copy_sizes_index < countof(copy_sizes);
526*344aa361SAndroid Build Coastguard Worker          copy_sizes_index++) {
527*344aa361SAndroid Build Coastguard Worker         copy_size = copy_sizes[copy_sizes_index];
528*344aa361SAndroid Build Coastguard Worker         for (null_off = TEST_BUF_COPY_START; null_off < TEST_BUF_SIZE;
529*344aa361SAndroid Build Coastguard Worker              null_off++) {
530*344aa361SAndroid Build Coastguard Worker             usercopy_test_strlcpy_from_user_inner(addr, arch_mmu_flags_start,
531*344aa361SAndroid Build Coastguard Worker                                                   arch_mmu_flags_end, copy_size,
532*344aa361SAndroid Build Coastguard Worker                                                   null_off);
533*344aa361SAndroid Build Coastguard Worker         }
534*344aa361SAndroid Build Coastguard Worker     }
535*344aa361SAndroid Build Coastguard Worker }
536*344aa361SAndroid Build Coastguard Worker 
flags_to_str(uint32_t flags)537*344aa361SAndroid Build Coastguard Worker static const char* flags_to_str(uint32_t flags) {
538*344aa361SAndroid Build Coastguard Worker     switch (flags) {
539*344aa361SAndroid Build Coastguard Worker     case FLAGS_NO_PAGE:
540*344aa361SAndroid Build Coastguard Worker         return "--";
541*344aa361SAndroid Build Coastguard Worker     case FLAGS_NO_USER:
542*344aa361SAndroid Build Coastguard Worker         return "ko";
543*344aa361SAndroid Build Coastguard Worker     case FLAGS_RO_USER:
544*344aa361SAndroid Build Coastguard Worker         return "ro";
545*344aa361SAndroid Build Coastguard Worker     case FLAGS_RW_USER:
546*344aa361SAndroid Build Coastguard Worker         return "rw";
547*344aa361SAndroid Build Coastguard Worker     default:
548*344aa361SAndroid Build Coastguard Worker         return "??";
549*344aa361SAndroid Build Coastguard Worker     }
550*344aa361SAndroid Build Coastguard Worker }
551*344aa361SAndroid Build Coastguard Worker 
user_param_to_string(const void * param,char * buf,size_t buf_size)552*344aa361SAndroid Build Coastguard Worker static void user_param_to_string(const void* param,
553*344aa361SAndroid Build Coastguard Worker                                  char* buf,
554*344aa361SAndroid Build Coastguard Worker                                  size_t buf_size) {
555*344aa361SAndroid Build Coastguard Worker     uint32_t start_flags = get_start_flags_param();
556*344aa361SAndroid Build Coastguard Worker     uint32_t end_flags = get_end_flags_param();
557*344aa361SAndroid Build Coastguard Worker     size_t count = 0;
558*344aa361SAndroid Build Coastguard Worker 
559*344aa361SAndroid Build Coastguard Worker     count = scnprintf(buf + count, buf_size - count, "%s",
560*344aa361SAndroid Build Coastguard Worker                       flags_to_str(start_flags));
561*344aa361SAndroid Build Coastguard Worker     scnprintf(buf + count, buf_size - count, "%s", flags_to_str(end_flags));
562*344aa361SAndroid Build Coastguard Worker }
563*344aa361SAndroid Build Coastguard Worker 
564*344aa361SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(UserCopyTestParams,
565*344aa361SAndroid Build Coastguard Worker                          usercopytest,
566*344aa361SAndroid Build Coastguard Worker                          testing_Combine(testing_Values(TEST_BUF_ADDR),
567*344aa361SAndroid Build Coastguard Worker                                          testing_Values(FLAGS_NO_PAGE,
568*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_NO_USER,
569*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_RO_USER,
570*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_RW_USER),
571*344aa361SAndroid Build Coastguard Worker                                          testing_Values(FLAGS_NO_PAGE,
572*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_NO_USER,
573*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_RO_USER,
574*344aa361SAndroid Build Coastguard Worker                                                         FLAGS_RW_USER)),
575*344aa361SAndroid Build Coastguard Worker                          user_param_to_string);
576*344aa361SAndroid Build Coastguard Worker 
577*344aa361SAndroid Build Coastguard Worker #if IS_64BIT && USER_32BIT
578*344aa361SAndroid Build Coastguard Worker /*
579*344aa361SAndroid Build Coastguard Worker  * Tests with Kernel addresses are not applicable to arm64u32 since kernel
580*344aa361SAndroid Build Coastguard Worker  * addresses do not fit in a user_addr_t.
581*344aa361SAndroid Build Coastguard Worker  */
582*344aa361SAndroid Build Coastguard Worker static_assert(KERNEL_BASE > UINT32_MAX);
583*344aa361SAndroid Build Coastguard Worker 
584*344aa361SAndroid Build Coastguard Worker PORT_TEST(usercopy_tests, PORT_NAME)
585*344aa361SAndroid Build Coastguard Worker 
586*344aa361SAndroid Build Coastguard Worker #else
587*344aa361SAndroid Build Coastguard Worker /* These are filled in before the tests are run */
588*344aa361SAndroid Build Coastguard Worker static user_addr_t kernel_addrs[3];
589*344aa361SAndroid Build Coastguard Worker 
590*344aa361SAndroid Build Coastguard Worker static void kernel_param_to_string(const void* param,
591*344aa361SAndroid Build Coastguard Worker                                    char* buf,
592*344aa361SAndroid Build Coastguard Worker                                    size_t buf_size) {
593*344aa361SAndroid Build Coastguard Worker     const void* const* kernel_param = param;
594*344aa361SAndroid Build Coastguard Worker     size_t idx = ((user_addr_t*)kernel_param[0] - kernel_addrs);
595*344aa361SAndroid Build Coastguard Worker     const char* str;
596*344aa361SAndroid Build Coastguard Worker 
597*344aa361SAndroid Build Coastguard Worker     switch (idx) {
598*344aa361SAndroid Build Coastguard Worker     case STACK_ADDR_IDX:
599*344aa361SAndroid Build Coastguard Worker         str = "kernel-stack";
600*344aa361SAndroid Build Coastguard Worker         break;
601*344aa361SAndroid Build Coastguard Worker     case HEAP_ADDR_IDX:
602*344aa361SAndroid Build Coastguard Worker         str = "kernel-heap";
603*344aa361SAndroid Build Coastguard Worker         break;
604*344aa361SAndroid Build Coastguard Worker     case GLOBAL_ADDR_IDX:
605*344aa361SAndroid Build Coastguard Worker         str = "kernel-global";
606*344aa361SAndroid Build Coastguard Worker         break;
607*344aa361SAndroid Build Coastguard Worker     default:
608*344aa361SAndroid Build Coastguard Worker         str = "unknown-address-type";
609*344aa361SAndroid Build Coastguard Worker     }
610*344aa361SAndroid Build Coastguard Worker 
611*344aa361SAndroid Build Coastguard Worker     scnprintf(buf, buf_size, "%s", str);
612*344aa361SAndroid Build Coastguard Worker }
613*344aa361SAndroid Build Coastguard Worker 
614*344aa361SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(KernelUserCopyTestParams,
615*344aa361SAndroid Build Coastguard Worker                          usercopytest,
616*344aa361SAndroid Build Coastguard Worker                          testing_Combine(testing_ValuesIn(kernel_addrs),
617*344aa361SAndroid Build Coastguard Worker                                          testing_Values(FLAGS_NO_USER),
618*344aa361SAndroid Build Coastguard Worker                                          testing_Values(FLAGS_NO_USER)),
619*344aa361SAndroid Build Coastguard Worker                          kernel_param_to_string);
620*344aa361SAndroid Build Coastguard Worker 
621*344aa361SAndroid Build Coastguard Worker static bool run_usercopy_test(struct unittest* test) {
622*344aa361SAndroid Build Coastguard Worker     bool tests_passed;
623*344aa361SAndroid Build Coastguard Worker     static uint8_t global_buf[TEST_BUF_SIZE];
624*344aa361SAndroid Build Coastguard Worker     uint8_t stack_buf[TEST_BUF_SIZE];
625*344aa361SAndroid Build Coastguard Worker     uint8_t* heap_buf = malloc(TEST_BUF_SIZE);
626*344aa361SAndroid Build Coastguard Worker 
627*344aa361SAndroid Build Coastguard Worker     ASSERT(heap_buf);
628*344aa361SAndroid Build Coastguard Worker 
629*344aa361SAndroid Build Coastguard Worker     kernel_addrs[STACK_ADDR_IDX] = (user_addr_t)stack_buf;
630*344aa361SAndroid Build Coastguard Worker     kernel_addrs[HEAP_ADDR_IDX] = (user_addr_t)heap_buf;
631*344aa361SAndroid Build Coastguard Worker     kernel_addrs[GLOBAL_ADDR_IDX] = (user_addr_t)global_buf;
632*344aa361SAndroid Build Coastguard Worker 
633*344aa361SAndroid Build Coastguard Worker     tests_passed = RUN_ALL_TESTS();
634*344aa361SAndroid Build Coastguard Worker 
635*344aa361SAndroid Build Coastguard Worker     free(heap_buf);
636*344aa361SAndroid Build Coastguard Worker 
637*344aa361SAndroid Build Coastguard Worker     return tests_passed;
638*344aa361SAndroid Build Coastguard Worker }
639*344aa361SAndroid Build Coastguard Worker 
640*344aa361SAndroid Build Coastguard Worker static void usercopy_test_init(uint level) {
641*344aa361SAndroid Build Coastguard Worker     static struct unittest usercopy_unittest = {
642*344aa361SAndroid Build Coastguard Worker             .port_name = PORT_NAME,
643*344aa361SAndroid Build Coastguard Worker             .run_test = run_usercopy_test,
644*344aa361SAndroid Build Coastguard Worker     };
645*344aa361SAndroid Build Coastguard Worker 
646*344aa361SAndroid Build Coastguard Worker     unittest_add(&usercopy_unittest);
647*344aa361SAndroid Build Coastguard Worker }
648*344aa361SAndroid Build Coastguard Worker 
649*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(usercopy_test, usercopy_test_init, LK_INIT_LEVEL_APPS);
650*344aa361SAndroid Build Coastguard Worker #endif  // !(IS_64BIT && USER_32BIT)
651