Skip to content

Commit cd58109

Browse files
hcahcaAlexander Gordeev
authored andcommitted
s390/stacktrace: Improve detection of invalid instruction pointers
Add basic checks to identify invalid instruction pointers when walking stack frames: Instruction pointers must - have even addresses - be larger than mmap_min_addr - lower than the asce_limit of the process Alternatively it would also be possible to walk page tables similar to fast GUP and verify that the mapping of the corresponding page is executable, however that seems to be overkill. Fixes: aa44433 ("s390: add USER_STACKTRACE support") Reviewed-by: Jens Remus <[email protected]> Signed-off-by: Heiko Carstens <[email protected]> Signed-off-by: Alexander Gordeev <[email protected]>
1 parent 87eceb1 commit cd58109

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

arch/s390/kernel/stacktrace.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,21 @@ static inline bool store_ip(stack_trace_consume_fn consume_entry, void *cookie,
7777
return consume_entry(cookie, ip);
7878
}
7979

80+
static inline bool ip_invalid(unsigned long ip)
81+
{
82+
/*
83+
* Perform some basic checks if an instruction address taken
84+
* from unreliable source is invalid.
85+
*/
86+
if (ip & 1)
87+
return true;
88+
if (ip < mmap_min_addr)
89+
return true;
90+
if (ip >= current->mm->context.asce_limit)
91+
return true;
92+
return false;
93+
}
94+
8095
void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *cookie,
8196
struct perf_callchain_entry_ctx *entry,
8297
const struct pt_regs *regs, bool perf)
@@ -87,6 +102,8 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
87102

88103
if (is_compat_task())
89104
return;
105+
if (!current->mm)
106+
return;
90107
ip = instruction_pointer(regs);
91108
if (!store_ip(consume_entry, cookie, entry, perf, ip))
92109
return;
@@ -101,15 +118,16 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
101118
sf = (void __user *)sp;
102119
if (__get_user(ip, &sf->gprs[8]))
103120
break;
104-
if (ip & 0x1) {
121+
if (ip_invalid(ip)) {
105122
/*
106123
* If the instruction address is invalid, and this
107124
* is the first stack frame, assume r14 has not
108125
* been written to the stack yet. Otherwise exit.
109126
*/
110-
if (first && !(regs->gprs[14] & 0x1))
111-
ip = regs->gprs[14];
112-
else
127+
if (!first)
128+
break;
129+
ip = regs->gprs[14];
130+
if (ip_invalid(ip))
113131
break;
114132
}
115133
if (!store_ip(consume_entry, cookie, entry, perf, ip))

0 commit comments

Comments
 (0)