1 /*
2  * Copyright (c) 2020 Google Inc. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <kernel/usercopy.h>
26 #include <lib/backtrace/backtrace.h>
27 #include <stdbool.h>
28 #include <string.h>
29 #include <uapi/err.h>
30 
31 /* Stack grows down */
32 const bool stack_direction = false;
33 
34 /**
35  * struct user_stack_frame - user-space stack frame
36  * @fp: frame pointer
37  * @lr: link register
38  *
39  * If user-space is explicitly 32-bit (e.g. 64u32 configuration), use 32 bits
40  * for register values. Otherwise, assume same bitness as the kernel.
41  */
42 struct user_stack_frame {
43 #if USER_32BIT
44     uint32_t fp;
45     uint32_t lr;
46 #else
47     uintptr_t fp;
48     uintptr_t lr;
49 #endif
50 };
51 
52 /**
53  * struct kernel_stack_frame - kernel-space stack frame
54  * @fp: frame pointer
55  * @lr: link register
56  */
57 struct kernel_stack_frame {
58     uintptr_t fp;
59     uintptr_t lr;
60 };
61 
step_user_frame(struct stack_frame * frame)62 static int step_user_frame(struct stack_frame* frame) {
63     struct user_stack_frame uframe;
64     int rc = copy_from_user(&uframe, frame->fp, sizeof(uframe));
65     if (rc != NO_ERROR) {
66         return FRAME_CORRUPT;
67     }
68 
69     frame->frame_addr = frame->fp;
70     frame->fp = uframe.fp;
71     frame->ret_addr = uframe.lr;
72     if (is_zero_frame(frame)) {
73         return FRAME_ZERO;
74     }
75     return FRAME_OK;
76 }
77 
step_kernel_frame(struct stack_frame * frame,bool current_frame)78 static int step_kernel_frame(struct stack_frame* frame, bool current_frame) {
79     struct kernel_stack_frame kframe;
80     void* frame_addr = current_frame ? __GET_FRAME() : (void*)(frame->fp);
81     memcpy(&kframe, frame_addr, sizeof(kframe));
82 
83     frame->frame_addr = (uintptr_t)frame_addr;
84     frame->fp = kframe.fp;
85     frame->ret_addr = kframe.lr;
86     if (is_zero_frame(frame)) {
87         return FRAME_ZERO;
88     }
89     return FRAME_OK;
90 }
91 
step_frame(struct stack_frame * frame,bool user)92 int step_frame(struct stack_frame* frame, bool user) {
93     if (user) {
94         return step_user_frame(frame);
95     } else {
96         return step_kernel_frame(frame, false);
97     }
98 }
99 
get_current_frame(struct stack_frame * frame)100 void get_current_frame(struct stack_frame* frame) {
101     step_kernel_frame(frame, true);
102 }
103