1 /* 2 * arch/arm64/kernel/sys32.c 3 * 4 * Copyright (C) 2015 ARM Ltd. 5 * 6 * This program is free software(void); you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http(void);//www.gnu.org/licenses/>. 17 */ 18 19 /* 20 * Needed to avoid conflicting __NR_* macros between uapi/asm/unistd.h and 21 * asm/unistd32.h. 22 */ 23 #define __COMPAT_SYSCALL_NR 24 25 #include <linux/compat.h> 26 #include <linux/compiler.h> 27 #include <linux/syscalls.h> 28 29 #include <asm/syscall.h> 30 31 asmlinkage long compat_sys_sigreturn(void); 32 asmlinkage long compat_sys_rt_sigreturn(void); 33 34 COMPAT_SYSCALL_DEFINE3(aarch32_statfs64, const char __user *, pathname, 35 compat_size_t, sz, struct compat_statfs64 __user *, buf) 36 { 37 /* 38 * 32-bit ARM applies an OABI compatibility fixup to statfs64 and 39 * fstatfs64 regardless of whether OABI is in use, and therefore 40 * arbitrary binaries may rely upon it, so we must do the same. 41 * For more details, see commit: 42 * 43 * 713c481519f19df9 ("[ARM] 3108/2: old ABI compat: statfs64 and 44 * fstatfs64") 45 */ 46 if (sz == 88) 47 sz = 84; 48 49 return kcompat_sys_statfs64(pathname, sz, buf); 50 } 51 52 COMPAT_SYSCALL_DEFINE3(aarch32_fstatfs64, unsigned int, fd, compat_size_t, sz, 53 struct compat_statfs64 __user *, buf) 54 { 55 /* see aarch32_statfs64 */ 56 if (sz == 88) 57 sz = 84; 58 59 return kcompat_sys_fstatfs64(fd, sz, buf); 60 } 61 62 /* 63 * Note: off_4k is always in units of 4K. If we can't do the 64 * requested offset because it is not page-aligned, we return -EINVAL. 65 */ 66 COMPAT_SYSCALL_DEFINE6(aarch32_mmap2, unsigned long, addr, unsigned long, len, 67 unsigned long, prot, unsigned long, flags, 68 unsigned long, fd, unsigned long, off_4k) 69 { 70 if (off_4k & (~PAGE_MASK >> 12)) 71 return -EINVAL; 72 73 off_4k >>= (PAGE_SHIFT - 12); 74 75 return ksys_mmap_pgoff(addr, len, prot, flags, fd, off_4k); 76 } 77 78 #ifdef CONFIG_CPU_BIG_ENDIAN 79 #define arg_u32p(name) u32, name##_hi, u32, name##_lo 80 #else 81 #define arg_u32p(name) u32, name##_lo, u32, name##_hi 82 #endif 83 84 #define arg_u64(name) (((u64)name##_hi << 32) | name##_lo) 85 86 COMPAT_SYSCALL_DEFINE6(aarch32_pread64, unsigned int, fd, char __user *, buf, 87 size_t, count, u32, __pad, arg_u32p(pos)) 88 { 89 return ksys_pread64(fd, buf, count, arg_u64(pos)); 90 } 91 92 COMPAT_SYSCALL_DEFINE6(aarch32_pwrite64, unsigned int, fd, 93 const char __user *, buf, size_t, count, u32, __pad, 94 arg_u32p(pos)) 95 { 96 return ksys_pwrite64(fd, buf, count, arg_u64(pos)); 97 } 98 99 COMPAT_SYSCALL_DEFINE4(aarch32_truncate64, const char __user *, pathname, 100 u32, __pad, arg_u32p(length)) 101 { 102 return ksys_truncate(pathname, arg_u64(length)); 103 } 104 105 COMPAT_SYSCALL_DEFINE4(aarch32_ftruncate64, unsigned int, fd, u32, __pad, 106 arg_u32p(length)) 107 { 108 return ksys_ftruncate(fd, arg_u64(length)); 109 } 110 111 COMPAT_SYSCALL_DEFINE5(aarch32_readahead, int, fd, u32, __pad, 112 arg_u32p(offset), size_t, count) 113 { 114 return ksys_readahead(fd, arg_u64(offset), count); 115 } 116 117 COMPAT_SYSCALL_DEFINE6(aarch32_fadvise64_64, int, fd, int, advice, 118 arg_u32p(offset), arg_u32p(len)) 119 { 120 return ksys_fadvise64_64(fd, arg_u64(offset), arg_u64(len), advice); 121 } 122 123 COMPAT_SYSCALL_DEFINE6(aarch32_sync_file_range2, int, fd, unsigned int, flags, 124 arg_u32p(offset), arg_u32p(nbytes)) 125 { 126 return ksys_sync_file_range(fd, arg_u64(offset), arg_u64(nbytes), 127 flags); 128 } 129 130 COMPAT_SYSCALL_DEFINE6(aarch32_fallocate, int, fd, int, mode, 131 arg_u32p(offset), arg_u32p(len)) 132 { 133 return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len)); 134 } 135 136 asmlinkage long sys_ni_syscall(const struct pt_regs *); 137 #define __arm64_sys_ni_syscall sys_ni_syscall 138 139 #undef __SYSCALL 140 #define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *); 141 #include <asm/unistd32.h> 142 143 #undef __SYSCALL 144 #define __SYSCALL(nr, sym) [nr] = (syscall_fn_t)__arm64_##sym, 145 146 const syscall_fn_t compat_sys_call_table[__NR_compat_syscalls] = { 147 [0 ... __NR_compat_syscalls - 1] = (syscall_fn_t)sys_ni_syscall, 148 #include <asm/unistd32.h> 149 }; 150