PageRenderTime 83ms CodeModel.GetById 2ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/sparc64/kernel/sys_sparc32.c

https://bitbucket.org/evzijst/gittest
C | 1118 lines | 912 code | 156 blank | 50 comment | 104 complexity | 8d8fd88137e627a513e56bd6d9da4d53 MD5 | raw file
   1/* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $
   2 * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
   3 *
   4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   6 *
   7 * These routines maintain argument size conversion between 32bit and 64bit
   8 * environment.
   9 */
  10
  11#include <linux/config.h>
  12#include <linux/kernel.h>
  13#include <linux/sched.h>
  14#include <linux/fs.h> 
  15#include <linux/mm.h> 
  16#include <linux/file.h> 
  17#include <linux/signal.h>
  18#include <linux/resource.h>
  19#include <linux/times.h>
  20#include <linux/utsname.h>
  21#include <linux/timex.h>
  22#include <linux/smp.h>
  23#include <linux/smp_lock.h>
  24#include <linux/sem.h>
  25#include <linux/msg.h>
  26#include <linux/shm.h>
  27#include <linux/slab.h>
  28#include <linux/uio.h>
  29#include <linux/nfs_fs.h>
  30#include <linux/quota.h>
  31#include <linux/module.h>
  32#include <linux/sunrpc/svc.h>
  33#include <linux/nfsd/nfsd.h>
  34#include <linux/nfsd/cache.h>
  35#include <linux/nfsd/xdr.h>
  36#include <linux/nfsd/syscall.h>
  37#include <linux/poll.h>
  38#include <linux/personality.h>
  39#include <linux/stat.h>
  40#include <linux/filter.h>
  41#include <linux/highmem.h>
  42#include <linux/highuid.h>
  43#include <linux/mman.h>
  44#include <linux/ipv6.h>
  45#include <linux/in.h>
  46#include <linux/icmpv6.h>
  47#include <linux/syscalls.h>
  48#include <linux/sysctl.h>
  49#include <linux/binfmts.h>
  50#include <linux/dnotify.h>
  51#include <linux/security.h>
  52#include <linux/compat.h>
  53#include <linux/vfs.h>
  54#include <linux/netfilter_ipv4/ip_tables.h>
  55#include <linux/ptrace.h>
  56#include <linux/highuid.h>
  57
  58#include <asm/types.h>
  59#include <asm/ipc.h>
  60#include <asm/uaccess.h>
  61#include <asm/fpumacro.h>
  62#include <asm/semaphore.h>
  63#include <asm/mmu_context.h>
  64
  65asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
  66{
  67	return sys_chown(filename, low2highuid(user), low2highgid(group));
  68}
  69
  70asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
  71{
  72	return sys_lchown(filename, low2highuid(user), low2highgid(group));
  73}
  74
  75asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
  76{
  77	return sys_fchown(fd, low2highuid(user), low2highgid(group));
  78}
  79
  80asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
  81{
  82	return sys_setregid(low2highgid(rgid), low2highgid(egid));
  83}
  84
  85asmlinkage long sys32_setgid16(u16 gid)
  86{
  87	return sys_setgid((gid_t)gid);
  88}
  89
  90asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
  91{
  92	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
  93}
  94
  95asmlinkage long sys32_setuid16(u16 uid)
  96{
  97	return sys_setuid((uid_t)uid);
  98}
  99
 100asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
 101{
 102	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
 103		low2highuid(suid));
 104}
 105
 106asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
 107{
 108	int retval;
 109
 110	if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
 111	    !(retval = put_user(high2lowuid(current->euid), euid)))
 112		retval = put_user(high2lowuid(current->suid), suid);
 113
 114	return retval;
 115}
 116
 117asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
 118{
 119	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
 120		low2highgid(sgid));
 121}
 122
 123asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
 124{
 125	int retval;
 126
 127	if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
 128	    !(retval = put_user(high2lowgid(current->egid), egid)))
 129		retval = put_user(high2lowgid(current->sgid), sgid);
 130
 131	return retval;
 132}
 133
 134asmlinkage long sys32_setfsuid16(u16 uid)
 135{
 136	return sys_setfsuid((uid_t)uid);
 137}
 138
 139asmlinkage long sys32_setfsgid16(u16 gid)
 140{
 141	return sys_setfsgid((gid_t)gid);
 142}
 143
 144static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
 145{
 146	int i;
 147	u16 group;
 148
 149	for (i = 0; i < group_info->ngroups; i++) {
 150		group = (u16)GROUP_AT(group_info, i);
 151		if (put_user(group, grouplist+i))
 152			return -EFAULT;
 153	}
 154
 155	return 0;
 156}
 157
 158static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
 159{
 160	int i;
 161	u16 group;
 162
 163	for (i = 0; i < group_info->ngroups; i++) {
 164		if (get_user(group, grouplist+i))
 165			return  -EFAULT;
 166		GROUP_AT(group_info, i) = (gid_t)group;
 167	}
 168
 169	return 0;
 170}
 171
 172asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
 173{
 174	int i;
 175
 176	if (gidsetsize < 0)
 177		return -EINVAL;
 178
 179	get_group_info(current->group_info);
 180	i = current->group_info->ngroups;
 181	if (gidsetsize) {
 182		if (i > gidsetsize) {
 183			i = -EINVAL;
 184			goto out;
 185		}
 186		if (groups16_to_user(grouplist, current->group_info)) {
 187			i = -EFAULT;
 188			goto out;
 189		}
 190	}
 191out:
 192	put_group_info(current->group_info);
 193	return i;
 194}
 195
 196asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
 197{
 198	struct group_info *group_info;
 199	int retval;
 200
 201	if (!capable(CAP_SETGID))
 202		return -EPERM;
 203	if ((unsigned)gidsetsize > NGROUPS_MAX)
 204		return -EINVAL;
 205
 206	group_info = groups_alloc(gidsetsize);
 207	if (!group_info)
 208		return -ENOMEM;
 209	retval = groups16_from_user(group_info, grouplist);
 210	if (retval) {
 211		put_group_info(group_info);
 212		return retval;
 213	}
 214
 215	retval = set_current_groups(group_info);
 216	put_group_info(group_info);
 217
 218	return retval;
 219}
 220
 221asmlinkage long sys32_getuid16(void)
 222{
 223	return high2lowuid(current->uid);
 224}
 225
 226asmlinkage long sys32_geteuid16(void)
 227{
 228	return high2lowuid(current->euid);
 229}
 230
 231asmlinkage long sys32_getgid16(void)
 232{
 233	return high2lowgid(current->gid);
 234}
 235
 236asmlinkage long sys32_getegid16(void)
 237{
 238	return high2lowgid(current->egid);
 239}
 240
 241/* 32-bit timeval and related flotsam.  */
 242
 243static long get_tv32(struct timeval *o, struct compat_timeval __user *i)
 244{
 245	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 246		(__get_user(o->tv_sec, &i->tv_sec) |
 247		 __get_user(o->tv_usec, &i->tv_usec)));
 248}
 249
 250static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
 251{
 252	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 253		(__put_user(i->tv_sec, &o->tv_sec) |
 254		 __put_user(i->tv_usec, &o->tv_usec)));
 255}
 256
 257#ifdef CONFIG_SYSVIPC                                                        
 258asmlinkage long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr, u32 fifth)
 259{
 260	int version;
 261
 262	version = call >> 16; /* hack for backward compatibility */
 263	call &= 0xffff;
 264
 265	switch (call) {
 266	case SEMTIMEDOP:
 267		if (fifth)
 268			/* sign extend semid */
 269			return compat_sys_semtimedop((int)first,
 270						     compat_ptr(ptr), second,
 271						     compat_ptr(fifth));
 272		/* else fall through for normal semop() */
 273	case SEMOP:
 274		/* struct sembuf is the same on 32 and 64bit :)) */
 275		/* sign extend semid */
 276		return sys_semtimedop((int)first, compat_ptr(ptr), second,
 277				      NULL);
 278	case SEMGET:
 279		/* sign extend key, nsems */
 280		return sys_semget((int)first, (int)second, third);
 281	case SEMCTL:
 282		/* sign extend semid, semnum */
 283		return compat_sys_semctl((int)first, (int)second, third,
 284					 compat_ptr(ptr));
 285
 286	case MSGSND:
 287		/* sign extend msqid */
 288		return compat_sys_msgsnd((int)first, (int)second, third,
 289					 compat_ptr(ptr));
 290	case MSGRCV:
 291		/* sign extend msqid, msgtyp */
 292		return compat_sys_msgrcv((int)first, second, (int)fifth,
 293					 third, version, compat_ptr(ptr));
 294	case MSGGET:
 295		/* sign extend key */
 296		return sys_msgget((int)first, second);
 297	case MSGCTL:
 298		/* sign extend msqid */
 299		return compat_sys_msgctl((int)first, second, compat_ptr(ptr));
 300
 301	case SHMAT:
 302		/* sign extend shmid */
 303		return compat_sys_shmat((int)first, second, third, version,
 304					compat_ptr(ptr));
 305	case SHMDT:
 306		return sys_shmdt(compat_ptr(ptr));
 307	case SHMGET:
 308		/* sign extend key_t */
 309		return sys_shmget((int)first, second, third);
 310	case SHMCTL:
 311		/* sign extend shmid */
 312		return compat_sys_shmctl((int)first, second, compat_ptr(ptr));
 313
 314	default:
 315		return -ENOSYS;
 316	};
 317
 318	return -ENOSYS;
 319}
 320#endif
 321
 322asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
 323{
 324	if ((int)high < 0)
 325		return -EINVAL;
 326	else
 327		return sys_truncate(path, (high << 32) | low);
 328}
 329
 330asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
 331{
 332	if ((int)high < 0)
 333		return -EINVAL;
 334	else
 335		return sys_ftruncate(fd, (high << 32) | low);
 336}
 337
 338int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
 339{
 340	int err;
 341
 342	if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
 343	    !old_valid_dev(stat->rdev))
 344		return -EOVERFLOW;
 345
 346	err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
 347	err |= put_user(stat->ino, &statbuf->st_ino);
 348	err |= put_user(stat->mode, &statbuf->st_mode);
 349	err |= put_user(stat->nlink, &statbuf->st_nlink);
 350	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
 351	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
 352	err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
 353	err |= put_user(stat->size, &statbuf->st_size);
 354	err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
 355	err |= put_user(0, &statbuf->__unused1);
 356	err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
 357	err |= put_user(0, &statbuf->__unused2);
 358	err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
 359	err |= put_user(0, &statbuf->__unused3);
 360	err |= put_user(stat->blksize, &statbuf->st_blksize);
 361	err |= put_user(stat->blocks, &statbuf->st_blocks);
 362	err |= put_user(0, &statbuf->__unused4[0]);
 363	err |= put_user(0, &statbuf->__unused4[1]);
 364
 365	return err;
 366}
 367
 368asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2)
 369{
 370	return sys_sysfs(option, arg1, arg2);
 371}
 372
 373struct sysinfo32 {
 374        s32 uptime;
 375        u32 loads[3];
 376        u32 totalram;
 377        u32 freeram;
 378        u32 sharedram;
 379        u32 bufferram;
 380        u32 totalswap;
 381        u32 freeswap;
 382        unsigned short procs;
 383	unsigned short pad;
 384	u32 totalhigh;
 385	u32 freehigh;
 386	u32 mem_unit;
 387	char _f[20-2*sizeof(int)-sizeof(int)];
 388};
 389
 390asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
 391{
 392	struct sysinfo s;
 393	int ret, err;
 394	int bitcount = 0;
 395	mm_segment_t old_fs = get_fs ();
 396	
 397	set_fs(KERNEL_DS);
 398	ret = sys_sysinfo((struct sysinfo __user *) &s);
 399	set_fs(old_fs);
 400	/* Check to see if any memory value is too large for 32-bit and
 401         * scale down if needed.
 402         */
 403	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
 404		while (s.mem_unit < PAGE_SIZE) {
 405			s.mem_unit <<= 1;
 406			bitcount++;
 407		}
 408		s.totalram >>= bitcount;
 409		s.freeram >>= bitcount;
 410		s.sharedram >>= bitcount;
 411		s.bufferram >>= bitcount;
 412		s.totalswap >>= bitcount;
 413		s.freeswap >>= bitcount;
 414		s.totalhigh >>= bitcount;
 415		s.freehigh >>= bitcount;
 416	}
 417
 418	err = put_user (s.uptime, &info->uptime);
 419	err |= __put_user (s.loads[0], &info->loads[0]);
 420	err |= __put_user (s.loads[1], &info->loads[1]);
 421	err |= __put_user (s.loads[2], &info->loads[2]);
 422	err |= __put_user (s.totalram, &info->totalram);
 423	err |= __put_user (s.freeram, &info->freeram);
 424	err |= __put_user (s.sharedram, &info->sharedram);
 425	err |= __put_user (s.bufferram, &info->bufferram);
 426	err |= __put_user (s.totalswap, &info->totalswap);
 427	err |= __put_user (s.freeswap, &info->freeswap);
 428	err |= __put_user (s.procs, &info->procs);
 429	err |= __put_user (s.totalhigh, &info->totalhigh);
 430	err |= __put_user (s.freehigh, &info->freehigh);
 431	err |= __put_user (s.mem_unit, &info->mem_unit);
 432	if (err)
 433		return -EFAULT;
 434	return ret;
 435}
 436
 437asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval)
 438{
 439	struct timespec t;
 440	int ret;
 441	mm_segment_t old_fs = get_fs ();
 442	
 443	set_fs (KERNEL_DS);
 444	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
 445	set_fs (old_fs);
 446	if (put_compat_timespec(&t, interval))
 447		return -EFAULT;
 448	return ret;
 449}
 450
 451asmlinkage long compat_sys_rt_sigprocmask(int how,
 452					  compat_sigset_t __user *set,
 453					  compat_sigset_t __user *oset,
 454					  compat_size_t sigsetsize)
 455{
 456	sigset_t s;
 457	compat_sigset_t s32;
 458	int ret;
 459	mm_segment_t old_fs = get_fs();
 460	
 461	if (set) {
 462		if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))
 463			return -EFAULT;
 464		switch (_NSIG_WORDS) {
 465		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
 466		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
 467		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
 468		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 469		}
 470	}
 471	set_fs (KERNEL_DS);
 472	ret = sys_rt_sigprocmask(how,
 473				 set ? (sigset_t __user *) &s : NULL,
 474				 oset ? (sigset_t __user *) &s : NULL,
 475				 sigsetsize);
 476	set_fs (old_fs);
 477	if (ret) return ret;
 478	if (oset) {
 479		switch (_NSIG_WORDS) {
 480		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
 481		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
 482		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 483		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 484		}
 485		if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))
 486			return -EFAULT;
 487	}
 488	return 0;
 489}
 490
 491asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
 492				    compat_size_t sigsetsize)
 493{
 494	sigset_t s;
 495	compat_sigset_t s32;
 496	int ret;
 497	mm_segment_t old_fs = get_fs();
 498		
 499	set_fs (KERNEL_DS);
 500	ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
 501	set_fs (old_fs);
 502	if (!ret) {
 503		switch (_NSIG_WORDS) {
 504		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
 505		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
 506		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 507		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 508		}
 509		if (copy_to_user (set, &s32, sizeof(compat_sigset_t)))
 510			return -EFAULT;
 511	}
 512	return ret;
 513}
 514
 515asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
 516					   struct compat_siginfo __user *uinfo)
 517{
 518	siginfo_t info;
 519	int ret;
 520	mm_segment_t old_fs = get_fs();
 521	
 522	if (copy_siginfo_from_user32(&info, uinfo))
 523		return -EFAULT;
 524
 525	set_fs (KERNEL_DS);
 526	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 527	set_fs (old_fs);
 528	return ret;
 529}
 530
 531asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
 532				     struct old_sigaction32 __user *oact)
 533{
 534        struct k_sigaction new_ka, old_ka;
 535        int ret;
 536
 537	if (sig < 0) {
 538		set_thread_flag(TIF_NEWSIGNALS);
 539		sig = -sig;
 540	}
 541
 542        if (act) {
 543		compat_old_sigset_t mask;
 544		u32 u_handler, u_restorer;
 545		
 546		ret = get_user(u_handler, &act->sa_handler);
 547		new_ka.sa.sa_handler =  compat_ptr(u_handler);
 548		ret |= __get_user(u_restorer, &act->sa_restorer);
 549		new_ka.sa.sa_restorer = compat_ptr(u_restorer);
 550		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 551		ret |= __get_user(mask, &act->sa_mask);
 552		if (ret)
 553			return ret;
 554		new_ka.ka_restorer = NULL;
 555		siginitset(&new_ka.sa.sa_mask, mask);
 556        }
 557
 558        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 559
 560	if (!ret && oact) {
 561		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
 562		ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
 563		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 564		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 565        }
 566
 567	return ret;
 568}
 569
 570asmlinkage long compat_sys_rt_sigaction(int sig,
 571					struct sigaction32 __user *act,
 572					struct sigaction32 __user *oact,
 573					void __user *restorer,
 574					compat_size_t sigsetsize)
 575{
 576        struct k_sigaction new_ka, old_ka;
 577        int ret;
 578	compat_sigset_t set32;
 579
 580        /* XXX: Don't preclude handling different sized sigset_t's.  */
 581        if (sigsetsize != sizeof(compat_sigset_t))
 582                return -EINVAL;
 583
 584	/* All tasks which use RT signals (effectively) use
 585	 * new style signals.
 586	 */
 587	set_thread_flag(TIF_NEWSIGNALS);
 588
 589        if (act) {
 590		u32 u_handler, u_restorer;
 591
 592		new_ka.ka_restorer = restorer;
 593		ret = get_user(u_handler, &act->sa_handler);
 594		new_ka.sa.sa_handler =  compat_ptr(u_handler);
 595		ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t));
 596		switch (_NSIG_WORDS) {
 597		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
 598		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
 599		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
 600		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
 601		}
 602		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 603		ret |= __get_user(u_restorer, &act->sa_restorer);
 604		new_ka.sa.sa_restorer = compat_ptr(u_restorer);
 605                if (ret)
 606                	return -EFAULT;
 607	}
 608
 609	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 610
 611	if (!ret && oact) {
 612		switch (_NSIG_WORDS) {
 613		case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
 614		case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
 615		case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
 616		case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
 617		}
 618		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
 619		ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t));
 620		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 621		ret |= __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer);
 622		if (ret)
 623			ret = -EFAULT;
 624        }
 625
 626        return ret;
 627}
 628
 629/*
 630 * sparc32_execve() executes a new program after the asm stub has set
 631 * things up for us.  This should basically do what I want it to.
 632 */
 633asmlinkage long sparc32_execve(struct pt_regs *regs)
 634{
 635	int error, base = 0;
 636	char *filename;
 637
 638	/* User register window flush is done by entry.S */
 639
 640	/* Check for indirect call. */
 641	if ((u32)regs->u_regs[UREG_G1] == 0)
 642		base = 1;
 643
 644	filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));
 645	error = PTR_ERR(filename);
 646	if (IS_ERR(filename))
 647		goto out;
 648
 649	error = compat_do_execve(filename,
 650				 compat_ptr(regs->u_regs[base + UREG_I1]),
 651				 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
 652
 653	putname(filename);
 654
 655	if (!error) {
 656		fprs_write(0);
 657		current_thread_info()->xfsr[0] = 0;
 658		current_thread_info()->fpsaved[0] = 0;
 659		regs->tstate &= ~TSTATE_PEF;
 660		task_lock(current);
 661		current->ptrace &= ~PT_DTRACE;
 662		task_unlock(current);
 663	}
 664out:
 665	return error;
 666}
 667
 668#ifdef CONFIG_MODULES
 669
 670asmlinkage long sys32_init_module(void __user *umod, u32 len,
 671				  const char __user *uargs)
 672{
 673	return sys_init_module(umod, len, uargs);
 674}
 675
 676asmlinkage long sys32_delete_module(const char __user *name_user,
 677				    unsigned int flags)
 678{
 679	return sys_delete_module(name_user, flags);
 680}
 681
 682#else /* CONFIG_MODULES */
 683
 684asmlinkage long sys32_init_module(const char __user *name_user,
 685				  struct module __user *mod_user)
 686{
 687	return -ENOSYS;
 688}
 689
 690asmlinkage long sys32_delete_module(const char __user *name_user)
 691{
 692	return -ENOSYS;
 693}
 694
 695#endif  /* CONFIG_MODULES */
 696
 697/* Translations due to time_t size differences.  Which affects all
 698   sorts of things, like timeval and itimerval.  */
 699
 700extern struct timezone sys_tz;
 701
 702asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv,
 703				   struct timezone __user *tz)
 704{
 705	if (tv) {
 706		struct timeval ktv;
 707		do_gettimeofday(&ktv);
 708		if (put_tv32(tv, &ktv))
 709			return -EFAULT;
 710	}
 711	if (tz) {
 712		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
 713			return -EFAULT;
 714	}
 715	return 0;
 716}
 717
 718static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
 719{
 720	long usec;
 721
 722	if (!access_ok(VERIFY_READ, i, sizeof(*i)))
 723		return -EFAULT;
 724	if (__get_user(o->tv_sec, &i->tv_sec))
 725		return -EFAULT;
 726	if (__get_user(usec, &i->tv_usec))
 727		return -EFAULT;
 728	o->tv_nsec = usec * 1000;
 729	return 0;
 730}
 731
 732asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
 733				   struct timezone __user *tz)
 734{
 735	struct timespec kts;
 736	struct timezone ktz;
 737
 738 	if (tv) {
 739		if (get_ts32(&kts, tv))
 740			return -EFAULT;
 741	}
 742	if (tz) {
 743		if (copy_from_user(&ktz, tz, sizeof(ktz)))
 744			return -EFAULT;
 745	}
 746
 747	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 748}
 749
 750asmlinkage long sys32_utimes(char __user *filename,
 751			     struct compat_timeval __user *tvs)
 752{
 753	struct timeval ktvs[2];
 754
 755	if (tvs) {
 756		if (get_tv32(&ktvs[0], tvs) ||
 757		    get_tv32(&ktvs[1], 1+tvs))
 758			return -EFAULT;
 759	}
 760
 761	return do_utimes(filename, (tvs ? &ktvs[0] : NULL));
 762}
 763
 764/* These are here just in case some old sparc32 binary calls it. */
 765asmlinkage long sys32_pause(void)
 766{
 767	current->state = TASK_INTERRUPTIBLE;
 768	schedule();
 769	return -ERESTARTNOHAND;
 770}
 771
 772asmlinkage compat_ssize_t sys32_pread64(unsigned int fd,
 773					char __user *ubuf,
 774					compat_size_t count,
 775					unsigned long poshi,
 776					unsigned long poslo)
 777{
 778	return sys_pread64(fd, ubuf, count, (poshi << 32) | poslo);
 779}
 780
 781asmlinkage compat_ssize_t sys32_pwrite64(unsigned int fd,
 782					 char __user *ubuf,
 783					 compat_size_t count,
 784					 unsigned long poshi,
 785					 unsigned long poslo)
 786{
 787	return sys_pwrite64(fd, ubuf, count, (poshi << 32) | poslo);
 788}
 789
 790asmlinkage long compat_sys_readahead(int fd,
 791				     unsigned long offhi,
 792				     unsigned long offlo,
 793				     compat_size_t count)
 794{
 795	return sys_readahead(fd, (offhi << 32) | offlo, count);
 796}
 797
 798long compat_sys_fadvise64(int fd,
 799			  unsigned long offhi,
 800			  unsigned long offlo,
 801			  compat_size_t len, int advice)
 802{
 803	return sys_fadvise64_64(fd, (offhi << 32) | offlo, len, advice);
 804}
 805
 806long compat_sys_fadvise64_64(int fd,
 807			     unsigned long offhi, unsigned long offlo,
 808			     unsigned long lenhi, unsigned long lenlo,
 809			     int advice)
 810{
 811	return sys_fadvise64_64(fd,
 812				(offhi << 32) | offlo,
 813				(lenhi << 32) | lenlo,
 814				advice);
 815}
 816
 817asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
 818				    compat_off_t __user *offset,
 819				    compat_size_t count)
 820{
 821	mm_segment_t old_fs = get_fs();
 822	int ret;
 823	off_t of;
 824	
 825	if (offset && get_user(of, offset))
 826		return -EFAULT;
 827		
 828	set_fs(KERNEL_DS);
 829	ret = sys_sendfile(out_fd, in_fd,
 830			   offset ? (off_t __user *) &of : NULL,
 831			   count);
 832	set_fs(old_fs);
 833	
 834	if (offset && put_user(of, offset))
 835		return -EFAULT;
 836		
 837	return ret;
 838}
 839
 840asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd,
 841				      compat_loff_t __user *offset,
 842				      compat_size_t count)
 843{
 844	mm_segment_t old_fs = get_fs();
 845	int ret;
 846	loff_t lof;
 847	
 848	if (offset && get_user(lof, offset))
 849		return -EFAULT;
 850		
 851	set_fs(KERNEL_DS);
 852	ret = sys_sendfile64(out_fd, in_fd,
 853			     offset ? (loff_t __user *) &lof : NULL,
 854			     count);
 855	set_fs(old_fs);
 856	
 857	if (offset && put_user(lof, offset))
 858		return -EFAULT;
 859		
 860	return ret;
 861}
 862
 863/* Handle adjtimex compatibility. */
 864
 865struct timex32 {
 866	u32 modes;
 867	s32 offset, freq, maxerror, esterror;
 868	s32 status, constant, precision, tolerance;
 869	struct compat_timeval time;
 870	s32 tick;
 871	s32 ppsfreq, jitter, shift, stabil;
 872	s32 jitcnt, calcnt, errcnt, stbcnt;
 873	s32  :32; s32  :32; s32  :32; s32  :32;
 874	s32  :32; s32  :32; s32  :32; s32  :32;
 875	s32  :32; s32  :32; s32  :32; s32  :32;
 876};
 877
 878extern int do_adjtimex(struct timex *);
 879
 880asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
 881{
 882	struct timex txc;
 883	int ret;
 884
 885	memset(&txc, 0, sizeof(struct timex));
 886
 887	if (get_user(txc.modes, &utp->modes) ||
 888	    __get_user(txc.offset, &utp->offset) ||
 889	    __get_user(txc.freq, &utp->freq) ||
 890	    __get_user(txc.maxerror, &utp->maxerror) ||
 891	    __get_user(txc.esterror, &utp->esterror) ||
 892	    __get_user(txc.status, &utp->status) ||
 893	    __get_user(txc.constant, &utp->constant) ||
 894	    __get_user(txc.precision, &utp->precision) ||
 895	    __get_user(txc.tolerance, &utp->tolerance) ||
 896	    __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
 897	    __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
 898	    __get_user(txc.tick, &utp->tick) ||
 899	    __get_user(txc.ppsfreq, &utp->ppsfreq) ||
 900	    __get_user(txc.jitter, &utp->jitter) ||
 901	    __get_user(txc.shift, &utp->shift) ||
 902	    __get_user(txc.stabil, &utp->stabil) ||
 903	    __get_user(txc.jitcnt, &utp->jitcnt) ||
 904	    __get_user(txc.calcnt, &utp->calcnt) ||
 905	    __get_user(txc.errcnt, &utp->errcnt) ||
 906	    __get_user(txc.stbcnt, &utp->stbcnt))
 907		return -EFAULT;
 908
 909	ret = do_adjtimex(&txc);
 910
 911	if (put_user(txc.modes, &utp->modes) ||
 912	    __put_user(txc.offset, &utp->offset) ||
 913	    __put_user(txc.freq, &utp->freq) ||
 914	    __put_user(txc.maxerror, &utp->maxerror) ||
 915	    __put_user(txc.esterror, &utp->esterror) ||
 916	    __put_user(txc.status, &utp->status) ||
 917	    __put_user(txc.constant, &utp->constant) ||
 918	    __put_user(txc.precision, &utp->precision) ||
 919	    __put_user(txc.tolerance, &utp->tolerance) ||
 920	    __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
 921	    __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
 922	    __put_user(txc.tick, &utp->tick) ||
 923	    __put_user(txc.ppsfreq, &utp->ppsfreq) ||
 924	    __put_user(txc.jitter, &utp->jitter) ||
 925	    __put_user(txc.shift, &utp->shift) ||
 926	    __put_user(txc.stabil, &utp->stabil) ||
 927	    __put_user(txc.jitcnt, &utp->jitcnt) ||
 928	    __put_user(txc.calcnt, &utp->calcnt) ||
 929	    __put_user(txc.errcnt, &utp->errcnt) ||
 930	    __put_user(txc.stbcnt, &utp->stbcnt))
 931		ret = -EFAULT;
 932
 933	return ret;
 934}
 935
 936/* This is just a version for 32-bit applications which does
 937 * not force O_LARGEFILE on.
 938 */
 939
 940asmlinkage long sparc32_open(const char __user *filename,
 941			     int flags, int mode)
 942{
 943	char * tmp;
 944	int fd, error;
 945
 946	tmp = getname(filename);
 947	fd = PTR_ERR(tmp);
 948	if (!IS_ERR(tmp)) {
 949		fd = get_unused_fd();
 950		if (fd >= 0) {
 951			struct file * f = filp_open(tmp, flags, mode);
 952			error = PTR_ERR(f);
 953			if (IS_ERR(f))
 954				goto out_error;
 955			fd_install(fd, f);
 956		}
 957out:
 958		putname(tmp);
 959	}
 960	return fd;
 961
 962out_error:
 963	put_unused_fd(fd);
 964	fd = error;
 965	goto out;
 966}
 967
 968extern unsigned long do_mremap(unsigned long addr,
 969	unsigned long old_len, unsigned long new_len,
 970	unsigned long flags, unsigned long new_addr);
 971                
 972asmlinkage unsigned long sys32_mremap(unsigned long addr,
 973	unsigned long old_len, unsigned long new_len,
 974	unsigned long flags, u32 __new_addr)
 975{
 976	struct vm_area_struct *vma;
 977	unsigned long ret = -EINVAL;
 978	unsigned long new_addr = __new_addr;
 979
 980	if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
 981		goto out;
 982	if (addr > 0xf0000000UL - old_len)
 983		goto out;
 984	down_write(&current->mm->mmap_sem);
 985	if (flags & MREMAP_FIXED) {
 986		if (new_addr > 0xf0000000UL - new_len)
 987			goto out_sem;
 988	} else if (addr > 0xf0000000UL - new_len) {
 989		unsigned long map_flags = 0;
 990		struct file *file = NULL;
 991
 992		ret = -ENOMEM;
 993		if (!(flags & MREMAP_MAYMOVE))
 994			goto out_sem;
 995
 996		vma = find_vma(current->mm, addr);
 997		if (vma) {
 998			if (vma->vm_flags & VM_SHARED)
 999				map_flags |= MAP_SHARED;
1000			file = vma->vm_file;
1001		}
1002
1003		/* MREMAP_FIXED checked above. */
1004		new_addr = get_unmapped_area(file, addr, new_len,
1005				    vma ? vma->vm_pgoff : 0,
1006				    map_flags);
1007		ret = new_addr;
1008		if (new_addr & ~PAGE_MASK)
1009			goto out_sem;
1010		flags |= MREMAP_FIXED;
1011	}
1012	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
1013out_sem:
1014	up_write(&current->mm->mmap_sem);
1015out:
1016	return ret;       
1017}
1018
1019struct __sysctl_args32 {
1020	u32 name;
1021	int nlen;
1022	u32 oldval;
1023	u32 oldlenp;
1024	u32 newval;
1025	u32 newlen;
1026	u32 __unused[4];
1027};
1028
1029asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
1030{
1031#ifndef CONFIG_SYSCTL
1032	return -ENOSYS;
1033#else
1034	struct __sysctl_args32 tmp;
1035	int error;
1036	size_t oldlen, __user *oldlenp = NULL;
1037	unsigned long addr = (((unsigned long)&args->__unused[0]) + 7UL) & ~7UL;
1038
1039	if (copy_from_user(&tmp, args, sizeof(tmp)))
1040		return -EFAULT;
1041
1042	if (tmp.oldval && tmp.oldlenp) {
1043		/* Duh, this is ugly and might not work if sysctl_args
1044		   is in read-only memory, but do_sysctl does indirectly
1045		   a lot of uaccess in both directions and we'd have to
1046		   basically copy the whole sysctl.c here, and
1047		   glibc's __sysctl uses rw memory for the structure
1048		   anyway.  */
1049		if (get_user(oldlen, (u32 __user *)(unsigned long)tmp.oldlenp) ||
1050		    put_user(oldlen, (size_t __user *)addr))
1051			return -EFAULT;
1052		oldlenp = (size_t __user *)addr;
1053	}
1054
1055	lock_kernel();
1056	error = do_sysctl((int __user *)(unsigned long) tmp.name,
1057			  tmp.nlen,
1058			  (void __user *)(unsigned long) tmp.oldval,
1059			  oldlenp,
1060			  (void __user *)(unsigned long) tmp.newval,
1061			  tmp.newlen);
1062	unlock_kernel();
1063	if (oldlenp) {
1064		if (!error) {
1065			if (get_user(oldlen, (size_t __user *)addr) ||
1066			    put_user(oldlen, (u32 __user *)(unsigned long) tmp.oldlenp))
1067				error = -EFAULT;
1068		}
1069		if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
1070			error = -EFAULT;
1071	}
1072	return error;
1073#endif
1074}
1075
1076long sys32_lookup_dcookie(unsigned long cookie_high,
1077			  unsigned long cookie_low,
1078			  char __user *buf, size_t len)
1079{
1080	return sys_lookup_dcookie((cookie_high << 32) | cookie_low,
1081				  buf, len);
1082}
1083
1084extern asmlinkage long
1085sys_timer_create(clockid_t which_clock,
1086		 struct sigevent __user *timer_event_spec,
1087		 timer_t __user *created_timer_id);
1088
1089long
1090sys32_timer_create(u32 clock, struct compat_sigevent __user *se32,
1091		   timer_t __user *timer_id)
1092{
1093	struct sigevent se;
1094	mm_segment_t oldfs;
1095	timer_t t;
1096	long err;
1097
1098	if (se32 == NULL)
1099		return sys_timer_create(clock, NULL, timer_id);
1100
1101	if (get_compat_sigevent(&se, se32))
1102		return -EFAULT;
1103
1104	if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
1105		return -EFAULT;
1106
1107	oldfs = get_fs();
1108	set_fs(KERNEL_DS);
1109	err = sys_timer_create(clock,
1110			       (struct sigevent __user *) &se,
1111			       (timer_t __user *) &t);
1112	set_fs(oldfs);
1113
1114	if (!err)
1115		err = __put_user (t, timer_id);
1116
1117	return err;
1118}