Skip to content

Commit a163513

Browse files
committed
sys/syscalls: fix invalid value returned to userland
Since 278687c (interrupts: add and use thread_get_interrupt_frame()), we were storing the return value inside the interrupt_frame structure saved inside struct process when an interrupt is triggered. Changes to this frame are not reflected inside the actual frame used when returning to userland. Because of this, the return value for every syscall was that contained inside the EAX register before executing the syscall. Retreive and modify the actual interrupt frame located at the top of the thread's kernel stack.
1 parent 8ef074c commit a163513

2 files changed

Lines changed: 17 additions & 3 deletions

File tree

kernel/arch/i686/syscalls.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include <kernel/interrupts.h>
2+
#include <kernel/process.h>
23
#include <kernel/syscalls.h>
34

5+
/*
6+
*
7+
*/
48
void arch_syscall_get_args(interrupt_frame *frame, syscall_args_t *args)
59
{
610
args->nr = frame->stub.eax;
@@ -12,7 +16,17 @@ void arch_syscall_get_args(interrupt_frame *frame, syscall_args_t *args)
1216
args->arg6 = frame->stub.ebp;
1317
}
1418

15-
void arch_syscall_set_return_value(interrupt_frame *frame, u32 value)
19+
/*
20+
*
21+
*/
22+
void arch_syscall_set_return_value(u32 value)
1623
{
24+
struct interrupt_frame *frame;
25+
26+
/*
27+
* Update the value inside the **actual** interrupt frame used when
28+
* returning to userland.
29+
*/
30+
frame = (void *)current->context.esp0 - sizeof(struct interrupt_frame);
1731
frame->stub.eax = value;
1832
}

kernel/sys/syscalls.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static inline void trace_syscall_exit(const struct syscall *syscall, int ret)
4545
void arch_syscall_get_args(interrupt_frame *frame, syscall_args_t *args);
4646

4747
/** Set the value to be returned by the syscall */
48-
void arch_syscall_set_return_value(interrupt_frame *frame, u32 value);
48+
void arch_syscall_set_return_value(u32 value);
4949

5050
#define DECLARE_SYSCALL(name, vector, argc, ...) \
5151
[SYS_##name] = {#name, (void *)sys_##name, argc},
@@ -109,7 +109,7 @@ static interrupt_return_t syscall(void *data)
109109
trace_syscall_exit(syscall, ret);
110110

111111
syscall_exit:
112-
arch_syscall_set_return_value(frame, ret);
112+
arch_syscall_set_return_value(ret);
113113
return INTERRUPT_HANDLED;
114114
}
115115

0 commit comments

Comments
 (0)