compat_linux.c revision 24954a1418298058399581d6fcc4d46e928e1bf5
1/* 2 * arch/s390x/kernel/linux32.c 3 * 4 * S390 version 5 * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 7 * Gerhard Tonn (ton@de.ibm.com) 8 * Thomas Spatzier (tspat@de.ibm.com) 9 * 10 * Conversion between 31bit and 64bit native syscalls. 11 * 12 * Heavily inspired by the 32-bit Sparc compat code which is 13 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 14 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) 15 * 16 */ 17 18 19#include <linux/config.h> 20#include <linux/kernel.h> 21#include <linux/sched.h> 22#include <linux/fs.h> 23#include <linux/mm.h> 24#include <linux/file.h> 25#include <linux/signal.h> 26#include <linux/resource.h> 27#include <linux/times.h> 28#include <linux/utsname.h> 29#include <linux/timex.h> 30#include <linux/smp.h> 31#include <linux/smp_lock.h> 32#include <linux/sem.h> 33#include <linux/msg.h> 34#include <linux/shm.h> 35#include <linux/slab.h> 36#include <linux/uio.h> 37#include <linux/nfs_fs.h> 38#include <linux/quota.h> 39#include <linux/module.h> 40#include <linux/sunrpc/svc.h> 41#include <linux/nfsd/nfsd.h> 42#include <linux/nfsd/cache.h> 43#include <linux/nfsd/xdr.h> 44#include <linux/nfsd/syscall.h> 45#include <linux/poll.h> 46#include <linux/personality.h> 47#include <linux/stat.h> 48#include <linux/filter.h> 49#include <linux/highmem.h> 50#include <linux/highuid.h> 51#include <linux/mman.h> 52#include <linux/ipv6.h> 53#include <linux/in.h> 54#include <linux/icmpv6.h> 55#include <linux/syscalls.h> 56#include <linux/sysctl.h> 57#include <linux/binfmts.h> 58#include <linux/capability.h> 59#include <linux/compat.h> 60#include <linux/vfs.h> 61#include <linux/ptrace.h> 62#include <linux/fadvise.h> 63 64#include <asm/types.h> 65#include <asm/ipc.h> 66#include <asm/uaccess.h> 67#include <asm/semaphore.h> 68 69#include <net/scm.h> 70#include <net/sock.h> 71 72#include "compat_linux.h" 73 74 75/* For this source file, we want overflow handling. */ 76 77#undef high2lowuid 78#undef high2lowgid 79#undef low2highuid 80#undef low2highgid 81#undef SET_UID16 82#undef SET_GID16 83#undef NEW_TO_OLD_UID 84#undef NEW_TO_OLD_GID 85#undef SET_OLDSTAT_UID 86#undef SET_OLDSTAT_GID 87#undef SET_STAT_UID 88#undef SET_STAT_GID 89 90#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) 91#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) 92#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid) 93#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid) 94#define SET_UID16(var, uid) var = high2lowuid(uid) 95#define SET_GID16(var, gid) var = high2lowgid(gid) 96#define NEW_TO_OLD_UID(uid) high2lowuid(uid) 97#define NEW_TO_OLD_GID(gid) high2lowgid(gid) 98#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 99#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 100#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) 101#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) 102 103asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group) 104{ 105 return sys_chown(filename, low2highuid(user), low2highgid(group)); 106} 107 108asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group) 109{ 110 return sys_lchown(filename, low2highuid(user), low2highgid(group)); 111} 112 113asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) 114{ 115 return sys_fchown(fd, low2highuid(user), low2highgid(group)); 116} 117 118asmlinkage long sys32_setregid16(u16 rgid, u16 egid) 119{ 120 return sys_setregid(low2highgid(rgid), low2highgid(egid)); 121} 122 123asmlinkage long sys32_setgid16(u16 gid) 124{ 125 return sys_setgid((gid_t)gid); 126} 127 128asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) 129{ 130 return sys_setreuid(low2highuid(ruid), low2highuid(euid)); 131} 132 133asmlinkage long sys32_setuid16(u16 uid) 134{ 135 return sys_setuid((uid_t)uid); 136} 137 138asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) 139{ 140 return sys_setresuid(low2highuid(ruid), low2highuid(euid), 141 low2highuid(suid)); 142} 143 144asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) 145{ 146 int retval; 147 148 if (!(retval = put_user(high2lowuid(current->uid), ruid)) && 149 !(retval = put_user(high2lowuid(current->euid), euid))) 150 retval = put_user(high2lowuid(current->suid), suid); 151 152 return retval; 153} 154 155asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) 156{ 157 return sys_setresgid(low2highgid(rgid), low2highgid(egid), 158 low2highgid(sgid)); 159} 160 161asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) 162{ 163 int retval; 164 165 if (!(retval = put_user(high2lowgid(current->gid), rgid)) && 166 !(retval = put_user(high2lowgid(current->egid), egid))) 167 retval = put_user(high2lowgid(current->sgid), sgid); 168 169 return retval; 170} 171 172asmlinkage long sys32_setfsuid16(u16 uid) 173{ 174 return sys_setfsuid((uid_t)uid); 175} 176 177asmlinkage long sys32_setfsgid16(u16 gid) 178{ 179 return sys_setfsgid((gid_t)gid); 180} 181 182static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info) 183{ 184 int i; 185 u16 group; 186 187 for (i = 0; i < group_info->ngroups; i++) { 188 group = (u16)GROUP_AT(group_info, i); 189 if (put_user(group, grouplist+i)) 190 return -EFAULT; 191 } 192 193 return 0; 194} 195 196static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist) 197{ 198 int i; 199 u16 group; 200 201 for (i = 0; i < group_info->ngroups; i++) { 202 if (get_user(group, grouplist+i)) 203 return -EFAULT; 204 GROUP_AT(group_info, i) = (gid_t)group; 205 } 206 207 return 0; 208} 209 210asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist) 211{ 212 int i; 213 214 if (gidsetsize < 0) 215 return -EINVAL; 216 217 get_group_info(current->group_info); 218 i = current->group_info->ngroups; 219 if (gidsetsize) { 220 if (i > gidsetsize) { 221 i = -EINVAL; 222 goto out; 223 } 224 if (groups16_to_user(grouplist, current->group_info)) { 225 i = -EFAULT; 226 goto out; 227 } 228 } 229out: 230 put_group_info(current->group_info); 231 return i; 232} 233 234asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) 235{ 236 struct group_info *group_info; 237 int retval; 238 239 if (!capable(CAP_SETGID)) 240 return -EPERM; 241 if ((unsigned)gidsetsize > NGROUPS_MAX) 242 return -EINVAL; 243 244 group_info = groups_alloc(gidsetsize); 245 if (!group_info) 246 return -ENOMEM; 247 retval = groups16_from_user(group_info, grouplist); 248 if (retval) { 249 put_group_info(group_info); 250 return retval; 251 } 252 253 retval = set_current_groups(group_info); 254 put_group_info(group_info); 255 256 return retval; 257} 258 259asmlinkage long sys32_getuid16(void) 260{ 261 return high2lowuid(current->uid); 262} 263 264asmlinkage long sys32_geteuid16(void) 265{ 266 return high2lowuid(current->euid); 267} 268 269asmlinkage long sys32_getgid16(void) 270{ 271 return high2lowgid(current->gid); 272} 273 274asmlinkage long sys32_getegid16(void) 275{ 276 return high2lowgid(current->egid); 277} 278 279/* 32-bit timeval and related flotsam. */ 280 281static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i) 282{ 283 return (!access_ok(VERIFY_READ, o, sizeof(*o)) || 284 (__get_user(o->tv_sec, &i->tv_sec) || 285 __get_user(o->tv_usec, &i->tv_usec))); 286} 287 288static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) 289{ 290 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || 291 (__put_user(i->tv_sec, &o->tv_sec) || 292 __put_user(i->tv_usec, &o->tv_usec))); 293} 294 295/* 296 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. 297 * 298 * This is really horribly ugly. 299 */ 300asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr) 301{ 302 if (call >> 16) /* hack for backward compatibility */ 303 return -EINVAL; 304 305 call &= 0xffff; 306 307 switch (call) { 308 case SEMTIMEDOP: 309 return compat_sys_semtimedop(first, compat_ptr(ptr), 310 second, compat_ptr(third)); 311 case SEMOP: 312 /* struct sembuf is the same on 32 and 64bit :)) */ 313 return sys_semtimedop(first, compat_ptr(ptr), 314 second, NULL); 315 case SEMGET: 316 return sys_semget(first, second, third); 317 case SEMCTL: 318 return compat_sys_semctl(first, second, third, 319 compat_ptr(ptr)); 320 case MSGSND: 321 return compat_sys_msgsnd(first, second, third, 322 compat_ptr(ptr)); 323 case MSGRCV: 324 return compat_sys_msgrcv(first, second, 0, third, 325 0, compat_ptr(ptr)); 326 case MSGGET: 327 return sys_msgget((key_t) first, second); 328 case MSGCTL: 329 return compat_sys_msgctl(first, second, compat_ptr(ptr)); 330 case SHMAT: 331 return compat_sys_shmat(first, second, third, 332 0, compat_ptr(ptr)); 333 case SHMDT: 334 return sys_shmdt(compat_ptr(ptr)); 335 case SHMGET: 336 return sys_shmget(first, (unsigned)second, third); 337 case SHMCTL: 338 return compat_sys_shmctl(first, second, compat_ptr(ptr)); 339 } 340 341 return -ENOSYS; 342} 343 344asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low) 345{ 346 if ((int)high < 0) 347 return -EINVAL; 348 else 349 return sys_truncate(path, (high << 32) | low); 350} 351 352asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low) 353{ 354 if ((int)high < 0) 355 return -EINVAL; 356 else 357 return sys_ftruncate(fd, (high << 32) | low); 358} 359 360int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) 361{ 362 int err; 363 364 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev)) 365 return -EOVERFLOW; 366 367 err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev); 368 err |= put_user(stat->ino, &statbuf->st_ino); 369 err |= put_user(stat->mode, &statbuf->st_mode); 370 err |= put_user(stat->nlink, &statbuf->st_nlink); 371 err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid); 372 err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid); 373 err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev); 374 err |= put_user(stat->size, &statbuf->st_size); 375 err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); 376 err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); 377 err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); 378 err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); 379 err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); 380 err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); 381 err |= put_user(stat->blksize, &statbuf->st_blksize); 382 err |= put_user(stat->blocks, &statbuf->st_blocks); 383/* fixme 384 err |= put_user(0, &statbuf->__unused4[0]); 385 err |= put_user(0, &statbuf->__unused4[1]); 386*/ 387 return err; 388} 389 390struct sysinfo32 { 391 s32 uptime; 392 u32 loads[3]; 393 u32 totalram; 394 u32 freeram; 395 u32 sharedram; 396 u32 bufferram; 397 u32 totalswap; 398 u32 freeswap; 399 unsigned short procs; 400 unsigned short pads; 401 u32 totalhigh; 402 u32 freehigh; 403 unsigned int mem_unit; 404 char _f[8]; 405}; 406 407asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) 408{ 409 struct sysinfo s; 410 int ret, err; 411 mm_segment_t old_fs = get_fs (); 412 413 set_fs (KERNEL_DS); 414 ret = sys_sysinfo(&s); 415 set_fs (old_fs); 416 err = put_user (s.uptime, &info->uptime); 417 err |= __put_user (s.loads[0], &info->loads[0]); 418 err |= __put_user (s.loads[1], &info->loads[1]); 419 err |= __put_user (s.loads[2], &info->loads[2]); 420 err |= __put_user (s.totalram, &info->totalram); 421 err |= __put_user (s.freeram, &info->freeram); 422 err |= __put_user (s.sharedram, &info->sharedram); 423 err |= __put_user (s.bufferram, &info->bufferram); 424 err |= __put_user (s.totalswap, &info->totalswap); 425 err |= __put_user (s.freeswap, &info->freeswap); 426 err |= __put_user (s.procs, &info->procs); 427 err |= __put_user (s.totalhigh, &info->totalhigh); 428 err |= __put_user (s.freehigh, &info->freehigh); 429 err |= __put_user (s.mem_unit, &info->mem_unit); 430 if (err) 431 return -EFAULT; 432 return ret; 433} 434 435asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, 436 struct compat_timespec __user *interval) 437{ 438 struct timespec t; 439 int ret; 440 mm_segment_t old_fs = get_fs (); 441 442 set_fs (KERNEL_DS); 443 ret = sys_sched_rr_get_interval(pid, &t); 444 set_fs (old_fs); 445 if (put_compat_timespec(&t, interval)) 446 return -EFAULT; 447 return ret; 448} 449 450asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, 451 compat_sigset_t __user *oset, size_t sigsetsize) 452{ 453 sigset_t s; 454 compat_sigset_t s32; 455 int ret; 456 mm_segment_t old_fs = get_fs(); 457 458 if (set) { 459 if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) 460 return -EFAULT; 461 switch (_NSIG_WORDS) { 462 case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); 463 case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); 464 case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); 465 case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); 466 } 467 } 468 set_fs (KERNEL_DS); 469 ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize); 470 set_fs (old_fs); 471 if (ret) return ret; 472 if (oset) { 473 switch (_NSIG_WORDS) { 474 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 475 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 476 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 477 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 478 } 479 if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) 480 return -EFAULT; 481 } 482 return 0; 483} 484 485asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, 486 size_t sigsetsize) 487{ 488 sigset_t s; 489 compat_sigset_t s32; 490 int ret; 491 mm_segment_t old_fs = get_fs(); 492 493 set_fs (KERNEL_DS); 494 ret = sys_rt_sigpending(&s, sigsetsize); 495 set_fs (old_fs); 496 if (!ret) { 497 switch (_NSIG_WORDS) { 498 case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; 499 case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; 500 case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; 501 case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; 502 } 503 if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) 504 return -EFAULT; 505 } 506 return ret; 507} 508 509asmlinkage long 510sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) 511{ 512 siginfo_t info; 513 int ret; 514 mm_segment_t old_fs = get_fs(); 515 516 if (copy_siginfo_from_user32(&info, uinfo)) 517 return -EFAULT; 518 set_fs (KERNEL_DS); 519 ret = sys_rt_sigqueueinfo(pid, sig, &info); 520 set_fs (old_fs); 521 return ret; 522} 523 524/* 525 * sys32_execve() executes a new program after the asm stub has set 526 * things up for us. This should basically do what I want it to. 527 */ 528asmlinkage long 529sys32_execve(struct pt_regs regs) 530{ 531 int error; 532 char * filename; 533 534 filename = getname(compat_ptr(regs.orig_gpr2)); 535 error = PTR_ERR(filename); 536 if (IS_ERR(filename)) 537 goto out; 538 error = compat_do_execve(filename, compat_ptr(regs.gprs[3]), 539 compat_ptr(regs.gprs[4]), ®s); 540 if (error == 0) 541 { 542 task_lock(current); 543 current->ptrace &= ~PT_DTRACE; 544 task_unlock(current); 545 current->thread.fp_regs.fpc=0; 546 __asm__ __volatile__ 547 ("sr 0,0\n\t" 548 "sfpc 0,0\n\t" 549 : : :"0"); 550 } 551 putname(filename); 552out: 553 return error; 554} 555 556 557#ifdef CONFIG_MODULES 558 559asmlinkage long 560sys32_init_module(void __user *umod, unsigned long len, 561 const char __user *uargs) 562{ 563 return sys_init_module(umod, len, uargs); 564} 565 566asmlinkage long 567sys32_delete_module(const char __user *name_user, unsigned int flags) 568{ 569 return sys_delete_module(name_user, flags); 570} 571 572#else /* CONFIG_MODULES */ 573 574asmlinkage long 575sys32_init_module(void __user *umod, unsigned long len, 576 const char __user *uargs) 577{ 578 return -ENOSYS; 579} 580 581asmlinkage long 582sys32_delete_module(const char __user *name_user, unsigned int flags) 583{ 584 return -ENOSYS; 585} 586 587#endif /* CONFIG_MODULES */ 588 589/* Translations due to time_t size differences. Which affects all 590 sorts of things, like timeval and itimerval. */ 591 592extern struct timezone sys_tz; 593 594asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 595{ 596 if (tv) { 597 struct timeval ktv; 598 do_gettimeofday(&ktv); 599 if (put_tv32(tv, &ktv)) 600 return -EFAULT; 601 } 602 if (tz) { 603 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 604 return -EFAULT; 605 } 606 return 0; 607} 608 609static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) 610{ 611 long usec; 612 613 if (!access_ok(VERIFY_READ, i, sizeof(*i))) 614 return -EFAULT; 615 if (__get_user(o->tv_sec, &i->tv_sec)) 616 return -EFAULT; 617 if (__get_user(usec, &i->tv_usec)) 618 return -EFAULT; 619 o->tv_nsec = usec * 1000; 620 return 0; 621} 622 623asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 624{ 625 struct timespec kts; 626 struct timezone ktz; 627 628 if (tv) { 629 if (get_ts32(&kts, tv)) 630 return -EFAULT; 631 } 632 if (tz) { 633 if (copy_from_user(&ktz, tz, sizeof(ktz))) 634 return -EFAULT; 635 } 636 637 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 638} 639 640/* These are here just in case some old sparc32 binary calls it. */ 641asmlinkage long sys32_pause(void) 642{ 643 current->state = TASK_INTERRUPTIBLE; 644 schedule(); 645 return -ERESTARTNOHAND; 646} 647 648asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, 649 size_t count, u32 poshi, u32 poslo) 650{ 651 if ((compat_ssize_t) count < 0) 652 return -EINVAL; 653 return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 654} 655 656asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf, 657 size_t count, u32 poshi, u32 poslo) 658{ 659 if ((compat_ssize_t) count < 0) 660 return -EINVAL; 661 return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); 662} 663 664asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) 665{ 666 return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); 667} 668 669asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count) 670{ 671 mm_segment_t old_fs = get_fs(); 672 int ret; 673 off_t of; 674 675 if (offset && get_user(of, offset)) 676 return -EFAULT; 677 678 set_fs(KERNEL_DS); 679 ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); 680 set_fs(old_fs); 681 682 if (offset && put_user(of, offset)) 683 return -EFAULT; 684 685 return ret; 686} 687 688asmlinkage long sys32_sendfile64(int out_fd, int in_fd, 689 compat_loff_t __user *offset, s32 count) 690{ 691 mm_segment_t old_fs = get_fs(); 692 int ret; 693 loff_t lof; 694 695 if (offset && get_user(lof, offset)) 696 return -EFAULT; 697 698 set_fs(KERNEL_DS); 699 ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count); 700 set_fs(old_fs); 701 702 if (offset && put_user(lof, offset)) 703 return -EFAULT; 704 705 return ret; 706} 707 708/* Handle adjtimex compatibility. */ 709 710struct timex32 { 711 u32 modes; 712 s32 offset, freq, maxerror, esterror; 713 s32 status, constant, precision, tolerance; 714 struct compat_timeval time; 715 s32 tick; 716 s32 ppsfreq, jitter, shift, stabil; 717 s32 jitcnt, calcnt, errcnt, stbcnt; 718 s32 :32; s32 :32; s32 :32; s32 :32; 719 s32 :32; s32 :32; s32 :32; s32 :32; 720 s32 :32; s32 :32; s32 :32; s32 :32; 721}; 722 723extern int do_adjtimex(struct timex *); 724 725asmlinkage long sys32_adjtimex(struct timex32 __user *utp) 726{ 727 struct timex txc; 728 int ret; 729 730 memset(&txc, 0, sizeof(struct timex)); 731 732 if(get_user(txc.modes, &utp->modes) || 733 __get_user(txc.offset, &utp->offset) || 734 __get_user(txc.freq, &utp->freq) || 735 __get_user(txc.maxerror, &utp->maxerror) || 736 __get_user(txc.esterror, &utp->esterror) || 737 __get_user(txc.status, &utp->status) || 738 __get_user(txc.constant, &utp->constant) || 739 __get_user(txc.precision, &utp->precision) || 740 __get_user(txc.tolerance, &utp->tolerance) || 741 __get_user(txc.time.tv_sec, &utp->time.tv_sec) || 742 __get_user(txc.time.tv_usec, &utp->time.tv_usec) || 743 __get_user(txc.tick, &utp->tick) || 744 __get_user(txc.ppsfreq, &utp->ppsfreq) || 745 __get_user(txc.jitter, &utp->jitter) || 746 __get_user(txc.shift, &utp->shift) || 747 __get_user(txc.stabil, &utp->stabil) || 748 __get_user(txc.jitcnt, &utp->jitcnt) || 749 __get_user(txc.calcnt, &utp->calcnt) || 750 __get_user(txc.errcnt, &utp->errcnt) || 751 __get_user(txc.stbcnt, &utp->stbcnt)) 752 return -EFAULT; 753 754 ret = do_adjtimex(&txc); 755 756 if(put_user(txc.modes, &utp->modes) || 757 __put_user(txc.offset, &utp->offset) || 758 __put_user(txc.freq, &utp->freq) || 759 __put_user(txc.maxerror, &utp->maxerror) || 760 __put_user(txc.esterror, &utp->esterror) || 761 __put_user(txc.status, &utp->status) || 762 __put_user(txc.constant, &utp->constant) || 763 __put_user(txc.precision, &utp->precision) || 764 __put_user(txc.tolerance, &utp->tolerance) || 765 __put_user(txc.time.tv_sec, &utp->time.tv_sec) || 766 __put_user(txc.time.tv_usec, &utp->time.tv_usec) || 767 __put_user(txc.tick, &utp->tick) || 768 __put_user(txc.ppsfreq, &utp->ppsfreq) || 769 __put_user(txc.jitter, &utp->jitter) || 770 __put_user(txc.shift, &utp->shift) || 771 __put_user(txc.stabil, &utp->stabil) || 772 __put_user(txc.jitcnt, &utp->jitcnt) || 773 __put_user(txc.calcnt, &utp->calcnt) || 774 __put_user(txc.errcnt, &utp->errcnt) || 775 __put_user(txc.stbcnt, &utp->stbcnt)) 776 ret = -EFAULT; 777 778 return ret; 779} 780 781#ifdef CONFIG_SYSCTL 782struct __sysctl_args32 { 783 u32 name; 784 int nlen; 785 u32 oldval; 786 u32 oldlenp; 787 u32 newval; 788 u32 newlen; 789 u32 __unused[4]; 790}; 791 792asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) 793{ 794 struct __sysctl_args32 tmp; 795 int error; 796 size_t oldlen; 797 size_t __user *oldlenp = NULL; 798 unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7; 799 800 if (copy_from_user(&tmp, args, sizeof(tmp))) 801 return -EFAULT; 802 803 if (tmp.oldval && tmp.oldlenp) { 804 /* Duh, this is ugly and might not work if sysctl_args 805 is in read-only memory, but do_sysctl does indirectly 806 a lot of uaccess in both directions and we'd have to 807 basically copy the whole sysctl.c here, and 808 glibc's __sysctl uses rw memory for the structure 809 anyway. */ 810 if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) || 811 put_user(oldlen, (size_t __user *)addr)) 812 return -EFAULT; 813 oldlenp = (size_t __user *)addr; 814 } 815 816 lock_kernel(); 817 error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval), 818 oldlenp, compat_ptr(tmp.newval), tmp.newlen); 819 unlock_kernel(); 820 if (oldlenp) { 821 if (!error) { 822 if (get_user(oldlen, (size_t __user *)addr) || 823 put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp))) 824 error = -EFAULT; 825 } 826 copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); 827 } 828 return error; 829} 830#endif 831 832struct stat64_emu31 { 833 unsigned long long st_dev; 834 unsigned int __pad1; 835#define STAT64_HAS_BROKEN_ST_INO 1 836 u32 __st_ino; 837 unsigned int st_mode; 838 unsigned int st_nlink; 839 u32 st_uid; 840 u32 st_gid; 841 unsigned long long st_rdev; 842 unsigned int __pad3; 843 long st_size; 844 u32 st_blksize; 845 unsigned char __pad4[4]; 846 u32 __pad5; /* future possible st_blocks high bits */ 847 u32 st_blocks; /* Number 512-byte blocks allocated. */ 848 u32 st_atime; 849 u32 __pad6; 850 u32 st_mtime; 851 u32 __pad7; 852 u32 st_ctime; 853 u32 __pad8; /* will be high 32 bits of ctime someday */ 854 unsigned long st_ino; 855}; 856 857static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat) 858{ 859 struct stat64_emu31 tmp; 860 861 memset(&tmp, 0, sizeof(tmp)); 862 863 tmp.st_dev = huge_encode_dev(stat->dev); 864 tmp.st_ino = stat->ino; 865 tmp.__st_ino = (u32)stat->ino; 866 tmp.st_mode = stat->mode; 867 tmp.st_nlink = (unsigned int)stat->nlink; 868 tmp.st_uid = stat->uid; 869 tmp.st_gid = stat->gid; 870 tmp.st_rdev = huge_encode_dev(stat->rdev); 871 tmp.st_size = stat->size; 872 tmp.st_blksize = (u32)stat->blksize; 873 tmp.st_blocks = (u32)stat->blocks; 874 tmp.st_atime = (u32)stat->atime.tv_sec; 875 tmp.st_mtime = (u32)stat->mtime.tv_sec; 876 tmp.st_ctime = (u32)stat->ctime.tv_sec; 877 878 return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; 879} 880 881asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf) 882{ 883 struct kstat stat; 884 int ret = vfs_stat(filename, &stat); 885 if (!ret) 886 ret = cp_stat64(statbuf, &stat); 887 return ret; 888} 889 890asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf) 891{ 892 struct kstat stat; 893 int ret = vfs_lstat(filename, &stat); 894 if (!ret) 895 ret = cp_stat64(statbuf, &stat); 896 return ret; 897} 898 899asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf) 900{ 901 struct kstat stat; 902 int ret = vfs_fstat(fd, &stat); 903 if (!ret) 904 ret = cp_stat64(statbuf, &stat); 905 return ret; 906} 907 908/* 909 * Linux/i386 didn't use to be able to handle more than 910 * 4 system call parameters, so these system calls used a memory 911 * block for parameter passing.. 912 */ 913 914struct mmap_arg_struct_emu31 { 915 u32 addr; 916 u32 len; 917 u32 prot; 918 u32 flags; 919 u32 fd; 920 u32 offset; 921}; 922 923/* common code for old and new mmaps */ 924static inline long do_mmap2( 925 unsigned long addr, unsigned long len, 926 unsigned long prot, unsigned long flags, 927 unsigned long fd, unsigned long pgoff) 928{ 929 struct file * file = NULL; 930 unsigned long error = -EBADF; 931 932 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); 933 if (!(flags & MAP_ANONYMOUS)) { 934 file = fget(fd); 935 if (!file) 936 goto out; 937 } 938 939 down_write(¤t->mm->mmap_sem); 940 error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); 941 if (!IS_ERR((void *) error) && error + len >= 0x80000000ULL) { 942 /* Result is out of bounds. */ 943 do_munmap(current->mm, addr, len); 944 error = -ENOMEM; 945 } 946 up_write(¤t->mm->mmap_sem); 947 948 if (file) 949 fput(file); 950out: 951 return error; 952} 953 954 955asmlinkage unsigned long 956old32_mmap(struct mmap_arg_struct_emu31 __user *arg) 957{ 958 struct mmap_arg_struct_emu31 a; 959 int error = -EFAULT; 960 961 if (copy_from_user(&a, arg, sizeof(a))) 962 goto out; 963 964 error = -EINVAL; 965 if (a.offset & ~PAGE_MASK) 966 goto out; 967 968 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 969out: 970 return error; 971} 972 973asmlinkage long 974sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) 975{ 976 struct mmap_arg_struct_emu31 a; 977 int error = -EFAULT; 978 979 if (copy_from_user(&a, arg, sizeof(a))) 980 goto out; 981 error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); 982out: 983 return error; 984} 985 986asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count) 987{ 988 if ((compat_ssize_t) count < 0) 989 return -EINVAL; 990 991 return sys_read(fd, buf, count); 992} 993 994asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) 995{ 996 if ((compat_ssize_t) count < 0) 997 return -EINVAL; 998 999 return sys_write(fd, buf, count); 1000} 1001 1002asmlinkage long sys32_clone(struct pt_regs regs) 1003{ 1004 unsigned long clone_flags; 1005 unsigned long newsp; 1006 int __user *parent_tidptr, *child_tidptr; 1007 1008 clone_flags = regs.gprs[3] & 0xffffffffUL; 1009 newsp = regs.orig_gpr2 & 0x7fffffffUL; 1010 parent_tidptr = compat_ptr(regs.gprs[4]); 1011 child_tidptr = compat_ptr(regs.gprs[5]); 1012 if (!newsp) 1013 newsp = regs.gprs[15]; 1014 return do_fork(clone_flags, newsp, ®s, 0, 1015 parent_tidptr, child_tidptr); 1016} 1017 1018/* 1019 * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. 1020 * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} 1021 * because the 31 bit values differ from the 64 bit values. 1022 */ 1023 1024asmlinkage long 1025sys32_fadvise64(int fd, loff_t offset, size_t len, int advise) 1026{ 1027 if (advise == 4) 1028 advise = POSIX_FADV_DONTNEED; 1029 else if (advise == 5) 1030 advise = POSIX_FADV_NOREUSE; 1031 return sys_fadvise64(fd, offset, len, advise); 1032} 1033 1034struct fadvise64_64_args { 1035 int fd; 1036 long long offset; 1037 long long len; 1038 int advice; 1039}; 1040 1041asmlinkage long 1042sys32_fadvise64_64(struct fadvise64_64_args __user *args) 1043{ 1044 struct fadvise64_64_args a; 1045 1046 if ( copy_from_user(&a, args, sizeof(a)) ) 1047 return -EFAULT; 1048 if (a.advice == 4) 1049 a.advice = POSIX_FADV_DONTNEED; 1050 else if (a.advice == 5) 1051 a.advice = POSIX_FADV_NOREUSE; 1052 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); 1053} 1054