mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
af33d2433b
If secure_computing() rejected a system call, we were previously setting the system call number to -1, to indicate to later code that the syscall failed. However, if something (e.g. a user notification) was sleeping, and received a signal, we may set a0 to -ERESTARTSYS and re-try the system call again. In this case, seccomp "denies" the syscall (because of the signal), and we would set a7 to -1, thus losing the value of the system call we want to restart. Instead, let's return -1 from do_syscall_trace_enter() to indicate that the syscall was rejected, so we don't clobber the value in case of -ERESTARTSYS or whatever. This commit fixes the user_notification_signal seccomp selftest on riscv to no longer hang. That test expects the system call to be re-issued after the signal, and it wasn't due to the above bug. Now that it is, everything works normally. Note that in the ptrace (tracer) case, the tracer can set the register values to whatever they want, so we still need to keep the code that handles out-of-bounds syscalls. However, we can drop the comment. We can also drop syscall_set_nr(), since it is no longer used anywhere, and the code that re-loads the value in a7 because of it. Reported in: https://lore.kernel.org/bpf/CAEn-LTp=ss0Dfv6J00=rCAy+N78U2AmhqJNjfqjr2FDpPYjxEQ@mail.gmail.com/ Reported-by: David Abdurachmanov <david.abdurachmanov@gmail.com> Signed-off-by: Tycho Andersen <tycho@tycho.ws> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
86 lines
2.0 KiB
C
86 lines
2.0 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
|
|
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
|
* Copyright 2015 Regents of the University of California, Berkeley
|
|
*
|
|
* See asm-generic/syscall.h for descriptions of what we must do here.
|
|
*/
|
|
|
|
#ifndef _ASM_RISCV_SYSCALL_H
|
|
#define _ASM_RISCV_SYSCALL_H
|
|
|
|
#include <uapi/linux/audit.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/err.h>
|
|
|
|
/* The array of function pointers for syscalls. */
|
|
extern void *sys_call_table[];
|
|
|
|
/*
|
|
* Only the low 32 bits of orig_r0 are meaningful, so we return int.
|
|
* This importantly ignores the high bits on 64-bit, so comparisons
|
|
* sign-extend the low 32 bits.
|
|
*/
|
|
static inline int syscall_get_nr(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
return regs->a7;
|
|
}
|
|
|
|
static inline void syscall_rollback(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
regs->a0 = regs->orig_a0;
|
|
}
|
|
|
|
static inline long syscall_get_error(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
unsigned long error = regs->a0;
|
|
|
|
return IS_ERR_VALUE(error) ? error : 0;
|
|
}
|
|
|
|
static inline long syscall_get_return_value(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
return regs->a0;
|
|
}
|
|
|
|
static inline void syscall_set_return_value(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
int error, long val)
|
|
{
|
|
regs->a0 = (long) error ?: val;
|
|
}
|
|
|
|
static inline void syscall_get_arguments(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
unsigned long *args)
|
|
{
|
|
args[0] = regs->orig_a0;
|
|
args++;
|
|
memcpy(args, ®s->a1, 5 * sizeof(args[0]));
|
|
}
|
|
|
|
static inline void syscall_set_arguments(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
const unsigned long *args)
|
|
{
|
|
regs->orig_a0 = args[0];
|
|
args++;
|
|
memcpy(®s->a1, args, 5 * sizeof(regs->a1));
|
|
}
|
|
|
|
static inline int syscall_get_arch(struct task_struct *task)
|
|
{
|
|
#ifdef CONFIG_64BIT
|
|
return AUDIT_ARCH_RISCV64;
|
|
#else
|
|
return AUDIT_ARCH_RISCV32;
|
|
#endif
|
|
}
|
|
|
|
#endif /* _ASM_RISCV_SYSCALL_H */
|