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