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 unsigned int p = personality & 0xffffffff; 255 int ret; 256 257 if (personality(current->personality) == PER_LINUX32 && 258 personality(p) == PER_LINUX) 259 p = (p & ~PER_MASK) | PER_LINUX32; 260 ret = sys_personality(p); 261 if (ret != -1 && personality(ret) == PER_LINUX32) 262 ret = (ret & ~PER_MASK) | PER_LINUX; 263 return ret; 264 } 265 266 SYSCALL_DEFINE4(32_sendfile, long, out_fd, long, in_fd, 267 compat_off_t __user *, offset, s32, count) 268 { 269 mm_segment_t old_fs = get_fs(); 270 int ret; 271 off_t of; 272 273 if (offset && get_user(of, offset)) 274 return -EFAULT; 275 276 set_fs(KERNEL_DS); 277 ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 278 set_fs(old_fs); 279 280 if (offset && put_user(of, offset)) 281 return -EFAULT; 282 283 return ret; 284 } 285 286 asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, 287 size_t count) 288 { 289 return sys_readahead(fd, merge_64(a2, a3), count); 290 } 291 292 asmlinkage long sys32_sync_file_range(int fd, int __pad, 293 unsigned long a2, unsigned long a3, 294 unsigned long a4, unsigned long a5, 295 int flags) 296 { 297 return sys_sync_file_range(fd, 298 merge_64(a2, a3), merge_64(a4, a5), 299 flags); 300 } 301 302 asmlinkage long sys32_fadvise64_64(int fd, int __pad, 303 unsigned long a2, unsigned long a3, 304 unsigned long a4, unsigned long a5, 305 int flags) 306 { 307 return sys_fadvise64_64(fd, 308 merge_64(a2, a3), merge_64(a4, a5), 309 flags); 310 } 311 312 asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2, 313 unsigned offset_a3, unsigned len_a4, unsigned len_a5) 314 { 315 return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3), 316 merge_64(len_a4, len_a5)); 317 } 318 319 save_static_function(sys32_clone); 320 static int noinline __used 321 _sys32_clone(nabi_no_regargs struct pt_regs regs) 322 { 323 unsigned long clone_flags; 324 unsigned long newsp; 325 int __user *parent_tidptr, *child_tidptr; 326 327 clone_flags = regs.regs[4]; 328 newsp = regs.regs[5]; 329 if (!newsp) 330 newsp = regs.regs[29]; 331 parent_tidptr = (int __user *) regs.regs[6]; 332 333 /* Use __dummy4 instead of getting it off the stack, so that 334 syscall() works. */ 335 child_tidptr = (int __user *) __dummy4; 336 return do_fork(clone_flags, newsp, ®s, 0, 337 parent_tidptr, child_tidptr); 338 } 339 340 asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf, 341 size_t len) 342 { 343 return sys_lookup_dcookie(merge_64(a0, a1), buf, len); 344 } 345 346 SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags, 347 u64, a3, u64, a4, int, dfd, const char __user *, pathname) 348 { 349 return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4), 350 dfd, pathname); 351 } 352 353 SYSCALL_DEFINE6(32_futex, u32 __user *, uaddr, int, op, u32, val, 354 struct compat_timespec __user *, utime, u32 __user *, uaddr2, 355 u32, val3) 356 { 357 return compat_sys_futex(uaddr, op, val, utime, uaddr2, val3); 358 } 359