1 /* 2 * Conversion between 32-bit and 64-bit native system calls. 3 * 4 * Copyright (C) 2000 Silicon Graphics, Inc. 5 * Written by Ulf Carlsson (ulfc@engr.sgi.com) 6 * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) 7 */ 8 #include <linux/compiler.h> 9 #include <linux/mm.h> 10 #include <linux/errno.h> 11 #include <linux/file.h> 12 #include <linux/highuid.h> 13 #include <linux/resource.h> 14 #include <linux/highmem.h> 15 #include <linux/time.h> 16 #include <linux/times.h> 17 #include <linux/poll.h> 18 #include <linux/skbuff.h> 19 #include <linux/filter.h> 20 #include <linux/shm.h> 21 #include <linux/sem.h> 22 #include <linux/msg.h> 23 #include <linux/icmpv6.h> 24 #include <linux/syscalls.h> 25 #include <linux/sysctl.h> 26 #include <linux/utime.h> 27 #include <linux/utsname.h> 28 #include <linux/personality.h> 29 #include <linux/dnotify.h> 30 #include <linux/module.h> 31 #include <linux/binfmts.h> 32 #include <linux/security.h> 33 #include <linux/compat.h> 34 #include <linux/vfs.h> 35 #include <linux/ipc.h> 36 #include <linux/slab.h> 37 38 #include <net/sock.h> 39 #include <net/scm.h> 40 41 #include <asm/compat-signal.h> 42 #include <asm/sim.h> 43 #include <asm/uaccess.h> 44 #include <asm/mmu_context.h> 45 #include <asm/mman.h> 46 47 /* Use this to get at 32-bit user passed pointers. */ 48 /* A() macro should be used for places where you e.g. 49 have some internal variable u32 and just want to get 50 rid of a compiler warning. AA() has to be used in 51 places where you want to convert a function argument 52 to 32bit pointer or when you e.g. access pt_regs 53 structure and want to consider 32bit registers only. 54 */ 55 #define A(__x) ((unsigned long)(__x)) 56 #define AA(__x) ((unsigned long)((int)__x)) 57 58 #ifdef __MIPSEB__ 59 #define merge_64(r1, r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL)) 60 #endif 61 #ifdef __MIPSEL__ 62 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) 63 #endif 64 65 SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len, 66 unsigned long, prot, unsigned long, flags, unsigned long, fd, 67 unsigned long, pgoff) 68 { 69 unsigned long error; 70 71 error = -EINVAL; 72 if (pgoff & (~PAGE_MASK >> 12)) 73 goto out; 74 error = sys_mmap_pgoff(addr, len, prot, flags, fd, 75 pgoff >> (PAGE_SHIFT-12)); 76 out: 77 return error; 78 } 79 80 /* 81 * sys_execve() executes a new program. 82 */ 83 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) 84 { 85 int error; 86 char * filename; 87 88 filename = getname(compat_ptr(regs.regs[4])); 89 error = PTR_ERR(filename); 90 if (IS_ERR(filename)) 91 goto out; 92 error = compat_do_execve(filename, compat_ptr(regs.regs[5]), 93 compat_ptr(regs.regs[6]), ®s); 94 putname(filename); 95 96 out: 97 return error; 98 } 99 100 #define RLIM_INFINITY32 0x7fffffff 101 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) 102 103 struct rlimit32 { 104 int rlim_cur; 105 int rlim_max; 106 }; 107 108 SYSCALL_DEFINE4(32_truncate64, const char __user *, path, 109 unsigned long, __dummy, unsigned long, a2, unsigned long, a3) 110 { 111 return sys_truncate(path, merge_64(a2, a3)); 112 } 113 114 SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy, 115 unsigned long, a2, unsigned long, a3) 116 { 117 return sys_ftruncate(fd, merge_64(a2, a3)); 118 } 119 120 SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high, 121 unsigned int, offset_low, loff_t __user *, result, 122 unsigned int, origin) 123 { 124 return sys_llseek(fd, offset_high, offset_low, result, origin); 125 } 126 127 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + 128 lseek back to original location. They fail just like lseek does on 129 non-seekable files. */ 130 131 SYSCALL_DEFINE6(32_pread, unsigned long, fd, char __user *, buf, size_t, count, 132 unsigned long, unused, unsigned long, a4, unsigned long, a5) 133 { 134 return sys_pread64(fd, buf, count, merge_64(a4, a5)); 135 } 136 137 SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf, 138 size_t, count, u32, unused, u64, a4, u64, a5) 139 { 140 return sys_pwrite64(fd, buf, count, merge_64(a4, a5)); 141 } 142 143 SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid, 144 struct compat_timespec __user *, interval) 145 { 146 struct timespec t; 147 int ret; 148 mm_segment_t old_fs = get_fs(); 149 150 set_fs(KERNEL_DS); 151 ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); 152 set_fs(old_fs); 153 if (put_user (t.tv_sec, &interval->tv_sec) || 154 __put_user(t.tv_nsec, &interval->tv_nsec)) 155 return -EFAULT; 156 return ret; 157 } 158 159 #ifdef CONFIG_SYSVIPC 160 161 SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third, 162 unsigned long, ptr, unsigned long, fifth) 163 { 164 int version, err; 165 166 version = call >> 16; /* hack for backward compatibility */ 167 call &= 0xffff; 168 169 switch (call) { 170 case SEMOP: 171 /* struct sembuf is the same on 32 and 64bit :)) */ 172 err = sys_semtimedop(first, compat_ptr(ptr), second, NULL); 173 break; 174 case SEMTIMEDOP: 175 err = compat_sys_semtimedop(first, compat_ptr(ptr), second, 176 compat_ptr(fifth)); 177 break; 178 case SEMGET: 179 err = sys_semget(first, second, third); 180 break; 181 case SEMCTL: 182 err = compat_sys_semctl(first, second, third, compat_ptr(ptr)); 183 break; 184 case MSGSND: 185 err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); 186 break; 187 case MSGRCV: 188 err = compat_sys_msgrcv(first, second, fifth, third, 189 version, compat_ptr(ptr)); 190 break; 191 case MSGGET: 192 err = sys_msgget((key_t) first, second); 193 break; 194 case MSGCTL: 195 err = compat_sys_msgctl(first, second, compat_ptr(ptr)); 196 break; 197 case SHMAT: 198 err = compat_sys_shmat(first, second, third, version, 199 compat_ptr(ptr)); 200 break; 201 case SHMDT: 202 err = sys_shmdt(compat_ptr(ptr)); 203 break; 204 case SHMGET: 205 err = sys_shmget(first, (unsigned)second, third); 206 break; 207 case SHMCTL: 208 err = compat_sys_shmctl(first, second, compat_ptr(ptr)); 209 break; 210 default: 211 err = -EINVAL; 212 break; 213 } 214 215 return err; 216 } 217 218 #else 219 220 SYSCALL_DEFINE6(32_ipc, u32, call, int, first, int, second, int, third, 221 u32, ptr, u32, fifth) 222 { 223 return -ENOSYS; 224 } 225 226 #endif /* CONFIG_SYSVIPC */ 227 228 #ifdef CONFIG_MIPS32_N32 229 SYSCALL_DEFINE4(n32_semctl, int, semid, int, semnum, int, cmd, u32, arg) 230 { 231 /* compat_sys_semctl expects a pointer to union semun */ 232 u32 __user *uptr = compat_alloc_user_space(sizeof(u32)); 233 if (put_user(arg, uptr)) 234 return -EFAULT; 235 return compat_sys_semctl(semid, semnum, cmd, uptr); 236 } 237 238 SYSCALL_DEFINE4(n32_msgsnd, int, msqid, u32, msgp, unsigned int, msgsz, 239 int, msgflg) 240 { 241 return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp)); 242 } 243 244 SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz, 245 int, msgtyp, int, msgflg) 246 { 247 return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64, 248 compat_ptr(msgp)); 249 } 250 #endif 251 252 SYSCALL_DEFINE1(32_personality, unsigned long, personality) 253 { 254 int ret; 255 personality &= 0xffffffff; 256 if (personality(current->personality) == PER_LINUX32 && 257 personality == PER_LINUX) 258 personality = PER_LINUX32; 259 ret = sys_personality(personality); 260 if (ret == PER_LINUX32) 261 ret = PER_LINUX; 262 return ret; 263 } 264 265 SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd, 266 compat_off_t __user *, offset, s32, count) 267 { 268 mm_segment_t old_fs = get_fs(); 269 int ret; 270 off_t of; 271 272 if (offset && get_user(of, offset)) 273 return -EFAULT; 274 275 set_fs(KERNEL_DS); 276 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 277 set_fs(old_fs); 278 279 if (offset && put_user(of, offset)) 280 return -EFAULT; 281 282 return ret; 283 } 284 285 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 286 size_t count) 287 { 288 return sys_readahead(fd, merge_64(a2, a3), count); 289 } 290 291 asmlinkage long sys32_sync_file_range(int fd, int __pad, 292 unsigned long a2, unsigned long a3, 293 unsigned long a4, unsigned long a5, 294 int flags) 295 { 296 return sys_sync_file_range(fd, 297 merge_64(a2, a3), merge_64(a4, a5), 298 flags); 299 } 300 301 asmlinkage long sys32_fadvise64_64(int fd, int __pad, 302 unsigned long a2, unsigned long a3, 303 unsigned long a4, unsigned long a5, 304 int flags) 305 { 306 return sys_fadvise64_64(fd, 307 merge_64(a2, a3), merge_64(a4, a5), 308 flags); 309 } 310 311 asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2, 312 unsigned offset_a3, unsigned len_a4, unsigned len_a5) 313 { 314 return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3), 315 merge_64(len_a4, len_a5)); 316 } 317 318 save_static_function(sys32_clone); 319 static int noinline __used 320 _sys32_clone(nabi_no_regargs struct pt_regs regs) 321 { 322 unsigned long clone_flags; 323 unsigned long newsp; 324 int __user *parent_tidptr, *child_tidptr; 325 326 clone_flags = regs.regs[4]; 327 newsp = regs.regs[5]; 328 if (!newsp) 329 newsp = regs.regs[29]; 330 parent_tidptr = (int __user *) regs.regs[6]; 331 332 /* Use __dummy4 instead of getting it off the stack, so that 333 syscall() works. */ 334 child_tidptr = (int __user *) __dummy4; 335 return do_fork(clone_flags, newsp, ®s, 0, 336 parent_tidptr, child_tidptr); 337 } 338 339 asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf, 340 size_t len) 341 { 342 return sys_lookup_dcookie(merge_64(a0, a1), buf, len); 343 } 344