mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-15 15:04:27 +08:00
61bf318eac
In https://bugs.gentoo.org/769614 Dmitry noticed that `ptrace(PTRACE_GET_SYSCALL_INFO)` does not return error sign properly. The bug is in mismatch between get/set errors: static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { return regs->r10 == -1 ? regs->r8:0; } static inline long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { return regs->r8; } static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { if (error) { /* error < 0, but ia64 uses > 0 return value */ regs->r8 = -error; regs->r10 = -1; } else { regs->r8 = val; regs->r10 = 0; } } Tested on v5.10 on rx3600 machine (ia64 9040 CPU). Link: https://lkml.kernel.org/r/20210221002554.333076-2-slyfox@gentoo.org Link: https://bugs.gentoo.org/769614 Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> Reported-by: Dmitry V. Levin <ldv@altlinux.org> Reviewed-by: Dmitry V. Levin <ldv@altlinux.org> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> Cc: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
79 lines
1.8 KiB
C
79 lines
1.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Access to user system call parameters and results
|
|
*
|
|
* Copyright (C) 2008 Intel Corp. Shaohua Li <shaohua.li@intel.com>
|
|
*
|
|
* See asm-generic/syscall.h for descriptions of what we must do here.
|
|
*/
|
|
|
|
#ifndef _ASM_SYSCALL_H
|
|
#define _ASM_SYSCALL_H 1
|
|
|
|
#include <uapi/linux/audit.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/err.h>
|
|
|
|
static inline long syscall_get_nr(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
if ((long)regs->cr_ifs < 0) /* Not a syscall */
|
|
return -1;
|
|
|
|
return regs->r15;
|
|
}
|
|
|
|
static inline void syscall_rollback(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
/* do nothing */
|
|
}
|
|
|
|
static inline long syscall_get_error(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
return regs->r10 == -1 ? -regs->r8:0;
|
|
}
|
|
|
|
static inline long syscall_get_return_value(struct task_struct *task,
|
|
struct pt_regs *regs)
|
|
{
|
|
return regs->r8;
|
|
}
|
|
|
|
static inline void syscall_set_return_value(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
int error, long val)
|
|
{
|
|
if (error) {
|
|
/* error < 0, but ia64 uses > 0 return value */
|
|
regs->r8 = -error;
|
|
regs->r10 = -1;
|
|
} else {
|
|
regs->r8 = val;
|
|
regs->r10 = 0;
|
|
}
|
|
}
|
|
|
|
extern void ia64_syscall_get_set_arguments(struct task_struct *task,
|
|
struct pt_regs *regs, unsigned long *args, int rw);
|
|
static inline void syscall_get_arguments(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
unsigned long *args)
|
|
{
|
|
ia64_syscall_get_set_arguments(task, regs, args, 0);
|
|
}
|
|
|
|
static inline void syscall_set_arguments(struct task_struct *task,
|
|
struct pt_regs *regs,
|
|
unsigned long *args)
|
|
{
|
|
ia64_syscall_get_set_arguments(task, regs, args, 1);
|
|
}
|
|
|
|
static inline int syscall_get_arch(struct task_struct *task)
|
|
{
|
|
return AUDIT_ARCH_IA64;
|
|
}
|
|
#endif /* _ASM_SYSCALL_H */
|