^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Access to user system call parameters and results
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * See asm-generic/syscall.h for descriptions of what we must do here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #ifndef _ASM_SYSCALL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define _ASM_SYSCALL_H 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <uapi/linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* ftrace syscalls requires exporting the sys_call_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) extern const unsigned long sys_call_table[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) extern const unsigned long compat_sys_call_table[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Note that we are returning an int here. That means 0xffffffff, ie.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 32-bit negative 1, will be interpreted as -1 on a 64-bit kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * This is important for seccomp so that compat tasks can set r0 = -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * to reject the syscall.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (trap_is_syscall(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return regs->gpr[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static inline void syscall_rollback(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) regs->gpr[3] = regs->orig_gpr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline long syscall_get_error(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (trap_is_scv(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned long error = regs->gpr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return IS_ERR_VALUE(error) ? error : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * If the system call failed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * regs->gpr[3] contains a positive ERRORCODE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static inline long syscall_get_return_value(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return regs->gpr[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static inline void syscall_set_return_value(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int error, long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (trap_is_scv(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) regs->gpr[3] = (long) error ?: val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * In the general case it's not obvious that we must deal with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * CCR here, as the syscall exit path will also do that for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * However there are some places, eg. the signal code, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * check ccr to decide if the value in r3 is actually an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) regs->ccr |= 0x10000000L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) regs->gpr[3] = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) regs->ccr &= ~0x10000000L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) regs->gpr[3] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static inline void syscall_get_arguments(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned long *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned long val, mask = -1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int n = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (test_tsk_thread_flag(task, TIF_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mask = 0xffffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) while (n--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (n == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) val = regs->orig_gpr3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) val = regs->gpr[3 + n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) args[n] = val & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline void syscall_set_arguments(struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct pt_regs *regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const unsigned long *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) memcpy(®s->gpr[3], args, 6 * sizeof(args[0]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* Also copy the first argument into orig_gpr3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) regs->orig_gpr3 = args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline int syscall_get_arch(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int arch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (IS_ENABLED(CONFIG_PPC64) && !test_tsk_thread_flag(task, TIF_32BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) arch = AUDIT_ARCH_PPC64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) arch = AUDIT_ARCH_PPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #ifdef __LITTLE_ENDIAN__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) arch |= __AUDIT_ARCH_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return arch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #endif /* _ASM_SYSCALL_H */