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