.. | .. |
---|
12 | 12 | * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca> |
---|
13 | 13 | */ |
---|
14 | 14 | |
---|
| 15 | +#include <linux/audit.h> |
---|
15 | 16 | #include <linux/errno.h> |
---|
16 | 17 | #include <linux/hw_breakpoint.h> |
---|
17 | 18 | #include <linux/kernel.h> |
---|
18 | 19 | #include <linux/mm.h> |
---|
19 | 20 | #include <linux/perf_event.h> |
---|
20 | 21 | #include <linux/ptrace.h> |
---|
| 22 | +#include <linux/regset.h> |
---|
21 | 23 | #include <linux/sched.h> |
---|
22 | 24 | #include <linux/sched/task_stack.h> |
---|
| 25 | +#include <linux/seccomp.h> |
---|
23 | 26 | #include <linux/security.h> |
---|
24 | 27 | #include <linux/signal.h> |
---|
25 | 28 | #include <linux/smp.h> |
---|
26 | 29 | #include <linux/tracehook.h> |
---|
27 | 30 | #include <linux/uaccess.h> |
---|
28 | 31 | |
---|
| 32 | +#define CREATE_TRACE_POINTS |
---|
| 33 | +#include <trace/events/syscalls.h> |
---|
| 34 | + |
---|
29 | 35 | #include <asm/coprocessor.h> |
---|
30 | 36 | #include <asm/elf.h> |
---|
31 | 37 | #include <asm/page.h> |
---|
32 | | -#include <asm/pgtable.h> |
---|
33 | 38 | #include <asm/ptrace.h> |
---|
34 | 39 | |
---|
| 40 | +static int gpr_get(struct task_struct *target, |
---|
| 41 | + const struct user_regset *regset, |
---|
| 42 | + struct membuf to) |
---|
| 43 | +{ |
---|
| 44 | + struct pt_regs *regs = task_pt_regs(target); |
---|
| 45 | + struct user_pt_regs newregs = { |
---|
| 46 | + .pc = regs->pc, |
---|
| 47 | + .ps = regs->ps & ~(1 << PS_EXCM_BIT), |
---|
| 48 | + .lbeg = regs->lbeg, |
---|
| 49 | + .lend = regs->lend, |
---|
| 50 | + .lcount = regs->lcount, |
---|
| 51 | + .sar = regs->sar, |
---|
| 52 | + .threadptr = regs->threadptr, |
---|
| 53 | + .windowbase = regs->windowbase, |
---|
| 54 | + .windowstart = regs->windowstart, |
---|
| 55 | + .syscall = regs->syscall, |
---|
| 56 | + }; |
---|
| 57 | + |
---|
| 58 | + memcpy(newregs.a, |
---|
| 59 | + regs->areg + XCHAL_NUM_AREGS - regs->windowbase * 4, |
---|
| 60 | + regs->windowbase * 16); |
---|
| 61 | + memcpy(newregs.a + regs->windowbase * 4, |
---|
| 62 | + regs->areg, |
---|
| 63 | + (WSBITS - regs->windowbase) * 16); |
---|
| 64 | + |
---|
| 65 | + return membuf_write(&to, &newregs, sizeof(newregs)); |
---|
| 66 | +} |
---|
| 67 | + |
---|
| 68 | +static int gpr_set(struct task_struct *target, |
---|
| 69 | + const struct user_regset *regset, |
---|
| 70 | + unsigned int pos, unsigned int count, |
---|
| 71 | + const void *kbuf, const void __user *ubuf) |
---|
| 72 | +{ |
---|
| 73 | + int ret; |
---|
| 74 | + struct user_pt_regs newregs = {0}; |
---|
| 75 | + struct pt_regs *regs; |
---|
| 76 | + const u32 ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; |
---|
| 77 | + |
---|
| 78 | + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1); |
---|
| 79 | + if (ret) |
---|
| 80 | + return ret; |
---|
| 81 | + |
---|
| 82 | + if (newregs.windowbase >= XCHAL_NUM_AREGS / 4) |
---|
| 83 | + return -EINVAL; |
---|
| 84 | + |
---|
| 85 | + regs = task_pt_regs(target); |
---|
| 86 | + regs->pc = newregs.pc; |
---|
| 87 | + regs->ps = (regs->ps & ~ps_mask) | (newregs.ps & ps_mask); |
---|
| 88 | + regs->lbeg = newregs.lbeg; |
---|
| 89 | + regs->lend = newregs.lend; |
---|
| 90 | + regs->lcount = newregs.lcount; |
---|
| 91 | + regs->sar = newregs.sar; |
---|
| 92 | + regs->threadptr = newregs.threadptr; |
---|
| 93 | + |
---|
| 94 | + if (newregs.syscall) |
---|
| 95 | + regs->syscall = newregs.syscall; |
---|
| 96 | + |
---|
| 97 | + if (newregs.windowbase != regs->windowbase || |
---|
| 98 | + newregs.windowstart != regs->windowstart) { |
---|
| 99 | + u32 rotws, wmask; |
---|
| 100 | + |
---|
| 101 | + rotws = (((newregs.windowstart | |
---|
| 102 | + (newregs.windowstart << WSBITS)) >> |
---|
| 103 | + newregs.windowbase) & |
---|
| 104 | + ((1 << WSBITS) - 1)) & ~1; |
---|
| 105 | + wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | |
---|
| 106 | + (rotws & 0xF) | 1; |
---|
| 107 | + regs->windowbase = newregs.windowbase; |
---|
| 108 | + regs->windowstart = newregs.windowstart; |
---|
| 109 | + regs->wmask = wmask; |
---|
| 110 | + } |
---|
| 111 | + |
---|
| 112 | + memcpy(regs->areg + XCHAL_NUM_AREGS - newregs.windowbase * 4, |
---|
| 113 | + newregs.a, newregs.windowbase * 16); |
---|
| 114 | + memcpy(regs->areg, newregs.a + newregs.windowbase * 4, |
---|
| 115 | + (WSBITS - newregs.windowbase) * 16); |
---|
| 116 | + |
---|
| 117 | + return 0; |
---|
| 118 | +} |
---|
| 119 | + |
---|
| 120 | +static int tie_get(struct task_struct *target, |
---|
| 121 | + const struct user_regset *regset, |
---|
| 122 | + struct membuf to) |
---|
| 123 | +{ |
---|
| 124 | + int ret; |
---|
| 125 | + struct pt_regs *regs = task_pt_regs(target); |
---|
| 126 | + struct thread_info *ti = task_thread_info(target); |
---|
| 127 | + elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL); |
---|
| 128 | + |
---|
| 129 | + if (!newregs) |
---|
| 130 | + return -ENOMEM; |
---|
| 131 | + |
---|
| 132 | + newregs->opt = regs->xtregs_opt; |
---|
| 133 | + newregs->user = ti->xtregs_user; |
---|
| 134 | + |
---|
| 135 | +#if XTENSA_HAVE_COPROCESSORS |
---|
| 136 | + /* Flush all coprocessor registers to memory. */ |
---|
| 137 | + coprocessor_flush_all(ti); |
---|
| 138 | + newregs->cp0 = ti->xtregs_cp.cp0; |
---|
| 139 | + newregs->cp1 = ti->xtregs_cp.cp1; |
---|
| 140 | + newregs->cp2 = ti->xtregs_cp.cp2; |
---|
| 141 | + newregs->cp3 = ti->xtregs_cp.cp3; |
---|
| 142 | + newregs->cp4 = ti->xtregs_cp.cp4; |
---|
| 143 | + newregs->cp5 = ti->xtregs_cp.cp5; |
---|
| 144 | + newregs->cp6 = ti->xtregs_cp.cp6; |
---|
| 145 | + newregs->cp7 = ti->xtregs_cp.cp7; |
---|
| 146 | +#endif |
---|
| 147 | + ret = membuf_write(&to, newregs, sizeof(*newregs)); |
---|
| 148 | + kfree(newregs); |
---|
| 149 | + return ret; |
---|
| 150 | +} |
---|
| 151 | + |
---|
| 152 | +static int tie_set(struct task_struct *target, |
---|
| 153 | + const struct user_regset *regset, |
---|
| 154 | + unsigned int pos, unsigned int count, |
---|
| 155 | + const void *kbuf, const void __user *ubuf) |
---|
| 156 | +{ |
---|
| 157 | + int ret; |
---|
| 158 | + struct pt_regs *regs = task_pt_regs(target); |
---|
| 159 | + struct thread_info *ti = task_thread_info(target); |
---|
| 160 | + elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL); |
---|
| 161 | + |
---|
| 162 | + if (!newregs) |
---|
| 163 | + return -ENOMEM; |
---|
| 164 | + |
---|
| 165 | + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
---|
| 166 | + newregs, 0, -1); |
---|
| 167 | + |
---|
| 168 | + if (ret) |
---|
| 169 | + goto exit; |
---|
| 170 | + regs->xtregs_opt = newregs->opt; |
---|
| 171 | + ti->xtregs_user = newregs->user; |
---|
| 172 | + |
---|
| 173 | +#if XTENSA_HAVE_COPROCESSORS |
---|
| 174 | + /* Flush all coprocessors before we overwrite them. */ |
---|
| 175 | + coprocessor_flush_all(ti); |
---|
| 176 | + coprocessor_release_all(ti); |
---|
| 177 | + ti->xtregs_cp.cp0 = newregs->cp0; |
---|
| 178 | + ti->xtregs_cp.cp1 = newregs->cp1; |
---|
| 179 | + ti->xtregs_cp.cp2 = newregs->cp2; |
---|
| 180 | + ti->xtregs_cp.cp3 = newregs->cp3; |
---|
| 181 | + ti->xtregs_cp.cp4 = newregs->cp4; |
---|
| 182 | + ti->xtregs_cp.cp5 = newregs->cp5; |
---|
| 183 | + ti->xtregs_cp.cp6 = newregs->cp6; |
---|
| 184 | + ti->xtregs_cp.cp7 = newregs->cp7; |
---|
| 185 | +#endif |
---|
| 186 | +exit: |
---|
| 187 | + kfree(newregs); |
---|
| 188 | + return ret; |
---|
| 189 | +} |
---|
| 190 | + |
---|
| 191 | +enum xtensa_regset { |
---|
| 192 | + REGSET_GPR, |
---|
| 193 | + REGSET_TIE, |
---|
| 194 | +}; |
---|
| 195 | + |
---|
| 196 | +static const struct user_regset xtensa_regsets[] = { |
---|
| 197 | + [REGSET_GPR] = { |
---|
| 198 | + .core_note_type = NT_PRSTATUS, |
---|
| 199 | + .n = sizeof(struct user_pt_regs) / sizeof(u32), |
---|
| 200 | + .size = sizeof(u32), |
---|
| 201 | + .align = sizeof(u32), |
---|
| 202 | + .regset_get = gpr_get, |
---|
| 203 | + .set = gpr_set, |
---|
| 204 | + }, |
---|
| 205 | + [REGSET_TIE] = { |
---|
| 206 | + .core_note_type = NT_PRFPREG, |
---|
| 207 | + .n = sizeof(elf_xtregs_t) / sizeof(u32), |
---|
| 208 | + .size = sizeof(u32), |
---|
| 209 | + .align = sizeof(u32), |
---|
| 210 | + .regset_get = tie_get, |
---|
| 211 | + .set = tie_set, |
---|
| 212 | + }, |
---|
| 213 | +}; |
---|
| 214 | + |
---|
| 215 | +static const struct user_regset_view user_xtensa_view = { |
---|
| 216 | + .name = "xtensa", |
---|
| 217 | + .e_machine = EM_XTENSA, |
---|
| 218 | + .regsets = xtensa_regsets, |
---|
| 219 | + .n = ARRAY_SIZE(xtensa_regsets) |
---|
| 220 | +}; |
---|
| 221 | + |
---|
| 222 | +const struct user_regset_view *task_user_regset_view(struct task_struct *task) |
---|
| 223 | +{ |
---|
| 224 | + return &user_xtensa_view; |
---|
| 225 | +} |
---|
35 | 226 | |
---|
36 | 227 | void user_enable_single_step(struct task_struct *child) |
---|
37 | 228 | { |
---|
38 | | - child->ptrace |= PT_SINGLESTEP; |
---|
| 229 | + set_tsk_thread_flag(child, TIF_SINGLESTEP); |
---|
39 | 230 | } |
---|
40 | 231 | |
---|
41 | 232 | void user_disable_single_step(struct task_struct *child) |
---|
42 | 233 | { |
---|
43 | | - child->ptrace &= ~PT_SINGLESTEP; |
---|
| 234 | + clear_tsk_thread_flag(child, TIF_SINGLESTEP); |
---|
44 | 235 | } |
---|
45 | 236 | |
---|
46 | 237 | /* |
---|
.. | .. |
---|
54 | 245 | |
---|
55 | 246 | static int ptrace_getregs(struct task_struct *child, void __user *uregs) |
---|
56 | 247 | { |
---|
57 | | - struct pt_regs *regs = task_pt_regs(child); |
---|
58 | | - xtensa_gregset_t __user *gregset = uregs; |
---|
59 | | - unsigned long wb = regs->windowbase; |
---|
60 | | - int i; |
---|
61 | | - |
---|
62 | | - if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) |
---|
63 | | - return -EIO; |
---|
64 | | - |
---|
65 | | - __put_user(regs->pc, &gregset->pc); |
---|
66 | | - __put_user(regs->ps & ~(1 << PS_EXCM_BIT), &gregset->ps); |
---|
67 | | - __put_user(regs->lbeg, &gregset->lbeg); |
---|
68 | | - __put_user(regs->lend, &gregset->lend); |
---|
69 | | - __put_user(regs->lcount, &gregset->lcount); |
---|
70 | | - __put_user(regs->windowstart, &gregset->windowstart); |
---|
71 | | - __put_user(regs->windowbase, &gregset->windowbase); |
---|
72 | | - __put_user(regs->threadptr, &gregset->threadptr); |
---|
73 | | - |
---|
74 | | - for (i = 0; i < XCHAL_NUM_AREGS; i++) |
---|
75 | | - __put_user(regs->areg[i], |
---|
76 | | - gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); |
---|
77 | | - |
---|
78 | | - return 0; |
---|
| 248 | + return copy_regset_to_user(child, &user_xtensa_view, REGSET_GPR, |
---|
| 249 | + 0, sizeof(xtensa_gregset_t), uregs); |
---|
79 | 250 | } |
---|
80 | 251 | |
---|
81 | 252 | static int ptrace_setregs(struct task_struct *child, void __user *uregs) |
---|
82 | 253 | { |
---|
83 | | - struct pt_regs *regs = task_pt_regs(child); |
---|
84 | | - xtensa_gregset_t *gregset = uregs; |
---|
85 | | - const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK; |
---|
86 | | - unsigned long ps; |
---|
87 | | - unsigned long wb, ws; |
---|
88 | | - |
---|
89 | | - if (!access_ok(VERIFY_WRITE, uregs, sizeof(xtensa_gregset_t))) |
---|
90 | | - return -EIO; |
---|
91 | | - |
---|
92 | | - __get_user(regs->pc, &gregset->pc); |
---|
93 | | - __get_user(ps, &gregset->ps); |
---|
94 | | - __get_user(regs->lbeg, &gregset->lbeg); |
---|
95 | | - __get_user(regs->lend, &gregset->lend); |
---|
96 | | - __get_user(regs->lcount, &gregset->lcount); |
---|
97 | | - __get_user(ws, &gregset->windowstart); |
---|
98 | | - __get_user(wb, &gregset->windowbase); |
---|
99 | | - __get_user(regs->threadptr, &gregset->threadptr); |
---|
100 | | - |
---|
101 | | - regs->ps = (regs->ps & ~ps_mask) | (ps & ps_mask) | (1 << PS_EXCM_BIT); |
---|
102 | | - |
---|
103 | | - if (wb >= XCHAL_NUM_AREGS / 4) |
---|
104 | | - return -EFAULT; |
---|
105 | | - |
---|
106 | | - if (wb != regs->windowbase || ws != regs->windowstart) { |
---|
107 | | - unsigned long rotws, wmask; |
---|
108 | | - |
---|
109 | | - rotws = (((ws | (ws << WSBITS)) >> wb) & |
---|
110 | | - ((1 << WSBITS) - 1)) & ~1; |
---|
111 | | - wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | |
---|
112 | | - (rotws & 0xF) | 1; |
---|
113 | | - regs->windowbase = wb; |
---|
114 | | - regs->windowstart = ws; |
---|
115 | | - regs->wmask = wmask; |
---|
116 | | - } |
---|
117 | | - |
---|
118 | | - if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, |
---|
119 | | - gregset->a, wb * 16)) |
---|
120 | | - return -EFAULT; |
---|
121 | | - |
---|
122 | | - if (__copy_from_user(regs->areg, gregset->a + wb * 4, |
---|
123 | | - (WSBITS - wb) * 16)) |
---|
124 | | - return -EFAULT; |
---|
125 | | - |
---|
126 | | - return 0; |
---|
| 254 | + return copy_regset_from_user(child, &user_xtensa_view, REGSET_GPR, |
---|
| 255 | + 0, sizeof(xtensa_gregset_t), uregs); |
---|
127 | 256 | } |
---|
128 | | - |
---|
129 | | - |
---|
130 | | -#if XTENSA_HAVE_COPROCESSORS |
---|
131 | | -#define CP_OFFSETS(cp) \ |
---|
132 | | - { \ |
---|
133 | | - .elf_xtregs_offset = offsetof(elf_xtregs_t, cp), \ |
---|
134 | | - .ti_offset = offsetof(struct thread_info, xtregs_cp.cp), \ |
---|
135 | | - .sz = sizeof(xtregs_ ## cp ## _t), \ |
---|
136 | | - } |
---|
137 | | - |
---|
138 | | -static const struct { |
---|
139 | | - size_t elf_xtregs_offset; |
---|
140 | | - size_t ti_offset; |
---|
141 | | - size_t sz; |
---|
142 | | -} cp_offsets[] = { |
---|
143 | | - CP_OFFSETS(cp0), |
---|
144 | | - CP_OFFSETS(cp1), |
---|
145 | | - CP_OFFSETS(cp2), |
---|
146 | | - CP_OFFSETS(cp3), |
---|
147 | | - CP_OFFSETS(cp4), |
---|
148 | | - CP_OFFSETS(cp5), |
---|
149 | | - CP_OFFSETS(cp6), |
---|
150 | | - CP_OFFSETS(cp7), |
---|
151 | | -}; |
---|
152 | | -#endif |
---|
153 | 257 | |
---|
154 | 258 | static int ptrace_getxregs(struct task_struct *child, void __user *uregs) |
---|
155 | 259 | { |
---|
156 | | - struct pt_regs *regs = task_pt_regs(child); |
---|
157 | | - struct thread_info *ti = task_thread_info(child); |
---|
158 | | - elf_xtregs_t __user *xtregs = uregs; |
---|
159 | | - int ret = 0; |
---|
160 | | - int i __maybe_unused; |
---|
161 | | - |
---|
162 | | - if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t))) |
---|
163 | | - return -EIO; |
---|
164 | | - |
---|
165 | | -#if XTENSA_HAVE_COPROCESSORS |
---|
166 | | - /* Flush all coprocessor registers to memory. */ |
---|
167 | | - coprocessor_flush_all(ti); |
---|
168 | | - |
---|
169 | | - for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i) |
---|
170 | | - ret |= __copy_to_user((char __user *)xtregs + |
---|
171 | | - cp_offsets[i].elf_xtregs_offset, |
---|
172 | | - (const char *)ti + |
---|
173 | | - cp_offsets[i].ti_offset, |
---|
174 | | - cp_offsets[i].sz); |
---|
175 | | -#endif |
---|
176 | | - ret |= __copy_to_user(&xtregs->opt, ®s->xtregs_opt, |
---|
177 | | - sizeof(xtregs->opt)); |
---|
178 | | - ret |= __copy_to_user(&xtregs->user,&ti->xtregs_user, |
---|
179 | | - sizeof(xtregs->user)); |
---|
180 | | - |
---|
181 | | - return ret ? -EFAULT : 0; |
---|
| 260 | + return copy_regset_to_user(child, &user_xtensa_view, REGSET_TIE, |
---|
| 261 | + 0, sizeof(elf_xtregs_t), uregs); |
---|
182 | 262 | } |
---|
183 | 263 | |
---|
184 | 264 | static int ptrace_setxregs(struct task_struct *child, void __user *uregs) |
---|
185 | 265 | { |
---|
186 | | - struct thread_info *ti = task_thread_info(child); |
---|
187 | | - struct pt_regs *regs = task_pt_regs(child); |
---|
188 | | - elf_xtregs_t *xtregs = uregs; |
---|
189 | | - int ret = 0; |
---|
190 | | - int i __maybe_unused; |
---|
191 | | - |
---|
192 | | - if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t))) |
---|
193 | | - return -EFAULT; |
---|
194 | | - |
---|
195 | | -#if XTENSA_HAVE_COPROCESSORS |
---|
196 | | - /* Flush all coprocessors before we overwrite them. */ |
---|
197 | | - coprocessor_flush_all(ti); |
---|
198 | | - coprocessor_release_all(ti); |
---|
199 | | - |
---|
200 | | - for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i) |
---|
201 | | - ret |= __copy_from_user((char *)ti + cp_offsets[i].ti_offset, |
---|
202 | | - (const char __user *)xtregs + |
---|
203 | | - cp_offsets[i].elf_xtregs_offset, |
---|
204 | | - cp_offsets[i].sz); |
---|
205 | | -#endif |
---|
206 | | - ret |= __copy_from_user(®s->xtregs_opt, &xtregs->opt, |
---|
207 | | - sizeof(xtregs->opt)); |
---|
208 | | - ret |= __copy_from_user(&ti->xtregs_user, &xtregs->user, |
---|
209 | | - sizeof(xtregs->user)); |
---|
210 | | - |
---|
211 | | - return ret ? -EFAULT : 0; |
---|
| 266 | + return copy_regset_from_user(child, &user_xtensa_view, REGSET_TIE, |
---|
| 267 | + 0, sizeof(elf_xtregs_t), uregs); |
---|
212 | 268 | } |
---|
213 | 269 | |
---|
214 | 270 | static int ptrace_peekusr(struct task_struct *child, long regno, |
---|
.. | .. |
---|
447 | 503 | void __user *datap = (void __user *) data; |
---|
448 | 504 | |
---|
449 | 505 | switch (request) { |
---|
450 | | - case PTRACE_PEEKTEXT: /* read word at location addr. */ |
---|
451 | | - case PTRACE_PEEKDATA: |
---|
452 | | - ret = generic_ptrace_peekdata(child, addr, data); |
---|
453 | | - break; |
---|
454 | | - |
---|
455 | 506 | case PTRACE_PEEKUSR: /* read register specified by addr. */ |
---|
456 | 507 | ret = ptrace_peekusr(child, addr, datap); |
---|
457 | | - break; |
---|
458 | | - |
---|
459 | | - case PTRACE_POKETEXT: /* write the word at location addr. */ |
---|
460 | | - case PTRACE_POKEDATA: |
---|
461 | | - ret = generic_ptrace_pokedata(child, addr, data); |
---|
462 | 508 | break; |
---|
463 | 509 | |
---|
464 | 510 | case PTRACE_POKEUSR: /* write register specified by addr. */ |
---|
.. | .. |
---|
497 | 543 | return ret; |
---|
498 | 544 | } |
---|
499 | 545 | |
---|
500 | | -unsigned long do_syscall_trace_enter(struct pt_regs *regs) |
---|
| 546 | +void do_syscall_trace_leave(struct pt_regs *regs); |
---|
| 547 | +int do_syscall_trace_enter(struct pt_regs *regs) |
---|
501 | 548 | { |
---|
502 | | - if (test_thread_flag(TIF_SYSCALL_TRACE) && |
---|
503 | | - tracehook_report_syscall_entry(regs)) |
---|
504 | | - return -1; |
---|
| 549 | + if (regs->syscall == NO_SYSCALL) |
---|
| 550 | + regs->areg[2] = -ENOSYS; |
---|
505 | 551 | |
---|
506 | | - return regs->areg[2]; |
---|
| 552 | + if (test_thread_flag(TIF_SYSCALL_TRACE) && |
---|
| 553 | + tracehook_report_syscall_entry(regs)) { |
---|
| 554 | + regs->areg[2] = -ENOSYS; |
---|
| 555 | + regs->syscall = NO_SYSCALL; |
---|
| 556 | + return 0; |
---|
| 557 | + } |
---|
| 558 | + |
---|
| 559 | + if (regs->syscall == NO_SYSCALL || |
---|
| 560 | + secure_computing() == -1) { |
---|
| 561 | + do_syscall_trace_leave(regs); |
---|
| 562 | + return 0; |
---|
| 563 | + } |
---|
| 564 | + |
---|
| 565 | + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
---|
| 566 | + trace_sys_enter(regs, syscall_get_nr(current, regs)); |
---|
| 567 | + |
---|
| 568 | + audit_syscall_entry(regs->syscall, regs->areg[6], |
---|
| 569 | + regs->areg[3], regs->areg[4], |
---|
| 570 | + regs->areg[5]); |
---|
| 571 | + return 1; |
---|
507 | 572 | } |
---|
508 | 573 | |
---|
509 | 574 | void do_syscall_trace_leave(struct pt_regs *regs) |
---|
510 | 575 | { |
---|
511 | 576 | int step; |
---|
512 | 577 | |
---|
| 578 | + audit_syscall_exit(regs); |
---|
| 579 | + |
---|
| 580 | + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
---|
| 581 | + trace_sys_exit(regs, regs_return_value(regs)); |
---|
| 582 | + |
---|
513 | 583 | step = test_thread_flag(TIF_SINGLESTEP); |
---|
514 | 584 | |
---|
515 | 585 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
---|