sys_sparc32.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,769 行 · 第 1/4 页

C
1,769
字号
/* $Id: sys_sparc32.c,v 1.184 2002/02/09 19:49:31 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * * These routines maintain argument size conversion between 32bit and 64bit * environment. */#include <linux/config.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h> #include <linux/mm.h> #include <linux/file.h> #include <linux/signal.h>#include <linux/resource.h>#include <linux/times.h>#include <linux/utsname.h>#include <linux/timex.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/sem.h>#include <linux/msg.h>#include <linux/shm.h>#include <linux/slab.h>#include <linux/uio.h>#include <linux/nfs_fs.h>#include <linux/quota.h>#include <linux/module.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr.h>#include <linux/nfsd/syscall.h>#include <linux/poll.h>#include <linux/personality.h>#include <linux/stat.h>#include <linux/filter.h>#include <linux/highmem.h>#include <linux/highuid.h>#include <linux/mman.h>#include <linux/ipv6.h>#include <linux/in.h>#include <linux/icmpv6.h>#include <linux/syscalls.h>#include <linux/sysctl.h>#include <linux/binfmts.h>#include <linux/dnotify.h>#include <linux/security.h>#include <linux/compat.h>#include <linux/vfs.h>#include <linux/netfilter_ipv4/ip_tables.h>#include <linux/ptrace.h>#include <linux/highuid.h>#include <asm/types.h>#include <asm/ipc.h>#include <asm/uaccess.h>#include <asm/fpumacro.h>#include <asm/semaphore.h>#include <asm/mmu_context.h>asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group){	return sys_chown(filename, low2highuid(user), low2highgid(group));}asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group){	return sys_lchown(filename, low2highuid(user), low2highgid(group));}asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group){	return sys_fchown(fd, low2highuid(user), low2highgid(group));}asmlinkage long sys32_setregid16(u16 rgid, u16 egid){	return sys_setregid(low2highgid(rgid), low2highgid(egid));}asmlinkage long sys32_setgid16(u16 gid){	return sys_setgid((gid_t)gid);}asmlinkage long sys32_setreuid16(u16 ruid, u16 euid){	return sys_setreuid(low2highuid(ruid), low2highuid(euid));}asmlinkage long sys32_setuid16(u16 uid){	return sys_setuid((uid_t)uid);}asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid){	return sys_setresuid(low2highuid(ruid), low2highuid(euid),		low2highuid(suid));}asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid){	int retval;	if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&	    !(retval = put_user(high2lowuid(current->euid), euid)))		retval = put_user(high2lowuid(current->suid), suid);	return retval;}asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid){	return sys_setresgid(low2highgid(rgid), low2highgid(egid),		low2highgid(sgid));}asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid){	int retval;	if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&	    !(retval = put_user(high2lowgid(current->egid), egid)))		retval = put_user(high2lowgid(current->sgid), sgid);	return retval;}asmlinkage long sys32_setfsuid16(u16 uid){	return sys_setfsuid((uid_t)uid);}asmlinkage long sys32_setfsgid16(u16 gid){	return sys_setfsgid((gid_t)gid);}static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info){	int i;	u16 group;	for (i = 0; i < group_info->ngroups; i++) {		group = (u16)GROUP_AT(group_info, i);		if (put_user(group, grouplist+i))			return -EFAULT;	}	return 0;}static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist){	int i;	u16 group;	for (i = 0; i < group_info->ngroups; i++) {		if (get_user(group, grouplist+i))			return  -EFAULT;		GROUP_AT(group_info, i) = (gid_t)group;	}	return 0;}asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist){	int i;	if (gidsetsize < 0)		return -EINVAL;	get_group_info(current->group_info);	i = current->group_info->ngroups;	if (gidsetsize) {		if (i > gidsetsize) {			i = -EINVAL;			goto out;		}		if (groups16_to_user(grouplist, current->group_info)) {			i = -EFAULT;			goto out;		}	}out:	put_group_info(current->group_info);	return i;}asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist){	struct group_info *group_info;	int retval;	if (!capable(CAP_SETGID))		return -EPERM;	if ((unsigned)gidsetsize > NGROUPS_MAX)		return -EINVAL;	group_info = groups_alloc(gidsetsize);	if (!group_info)		return -ENOMEM;	retval = groups16_from_user(group_info, grouplist);	if (retval) {		put_group_info(group_info);		return retval;	}	retval = set_current_groups(group_info);	put_group_info(group_info);	return retval;}asmlinkage long sys32_getuid16(void){	return high2lowuid(current->uid);}asmlinkage long sys32_geteuid16(void){	return high2lowuid(current->euid);}asmlinkage long sys32_getgid16(void){	return high2lowgid(current->gid);}asmlinkage long sys32_getegid16(void){	return high2lowgid(current->egid);}/* 32-bit timeval and related flotsam.  */static long get_tv32(struct timeval *o, struct compat_timeval __user *i){	return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||		(__get_user(o->tv_sec, &i->tv_sec) |		 __get_user(o->tv_usec, &i->tv_usec)));}static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i){	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||		(__put_user(i->tv_sec, &o->tv_sec) |		 __put_user(i->tv_usec, &o->tv_usec)));}struct msgbuf32 { s32 mtype; char mtext[1]; };struct ipc_perm32 {	key_t    	  key;        compat_uid_t  uid;        compat_gid_t  gid;        compat_uid_t  cuid;        compat_gid_t  cgid;        compat_mode_t mode;        unsigned short  seq;};struct semid_ds32 {        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */        compat_time_t   sem_otime;              /* last semop time */        compat_time_t   sem_ctime;              /* last change time */        u32 sem_base;              /* ptr to first semaphore in array */        u32 sem_pending;          /* pending operations to be processed */        u32 sem_pending_last;    /* last pending operation */        u32 undo;                  /* undo requests on this array */        unsigned short  sem_nsems;              /* no. of semaphores in array */};struct semid64_ds32 {	struct ipc64_perm sem_perm;		  /* this structure is the same on sparc32 and sparc64 */	unsigned int	  __pad1;	compat_time_t   sem_otime;	unsigned int	  __pad2;	compat_time_t   sem_ctime;	u32 sem_nsems;	u32 __unused1;	u32 __unused2;};struct msqid_ds32{        struct ipc_perm32 msg_perm;        u32 msg_first;        u32 msg_last;        compat_time_t   msg_stime;        compat_time_t   msg_rtime;        compat_time_t   msg_ctime;        u32 wwait;        u32 rwait;        unsigned short msg_cbytes;        unsigned short msg_qnum;          unsigned short msg_qbytes;        compat_ipc_pid_t msg_lspid;        compat_ipc_pid_t msg_lrpid;};struct msqid64_ds32 {	struct ipc64_perm msg_perm;	unsigned int   __pad1;	compat_time_t   msg_stime;	unsigned int   __pad2;	compat_time_t   msg_rtime;	unsigned int   __pad3;	compat_time_t   msg_ctime;	unsigned int  msg_cbytes;	unsigned int  msg_qnum;	unsigned int  msg_qbytes;	compat_pid_t msg_lspid;	compat_pid_t msg_lrpid;	unsigned int  __unused1;	unsigned int  __unused2;};struct shmid_ds32 {	struct ipc_perm32       shm_perm;	int                     shm_segsz;	compat_time_t         shm_atime;	compat_time_t         shm_dtime;	compat_time_t         shm_ctime;	compat_ipc_pid_t    shm_cpid; 	compat_ipc_pid_t    shm_lpid; 	unsigned short          shm_nattch;};struct shmid64_ds32 {	struct ipc64_perm	shm_perm;	unsigned int		__pad1;	compat_time_t  	shm_atime;	unsigned int		__pad2;	compat_time_t  	shm_dtime;	unsigned int		__pad3;	compat_time_t  	shm_ctime;	compat_size_t	shm_segsz;	compat_pid_t	shm_cpid;	compat_pid_t	shm_lpid;	unsigned int		shm_nattch;	unsigned int		__unused1;	unsigned int		__unused2;};                                                        /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * * This is really horribly ugly. */#define IPCOP_MASK(__x)	(1UL << ((__x)&~IPC_64))static int do_sys32_semctl(int first, int second, int third,			   compat_uptr_t __user *uptr){	union semun fourth;	compat_uptr_t pad;	int err = -EINVAL;	if (!uptr)		goto out;	err = -EFAULT;	if (get_user(pad, uptr))		goto out;	if ((third & ~IPC_64) == SETVAL)		fourth.val = (int)pad;	else		fourth.__pad = compat_ptr(pad);	if (IPCOP_MASK (third) &	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |	     IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {		err = sys_semctl (first, second, third, fourth);	} else if (third & IPC_64) {		struct semid64_ds s;		struct semid64_ds32 __user *usp = compat_ptr(pad);		mm_segment_t old_fs;		int need_back_translation;		if (third == (IPC_SET|IPC_64)) {			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);			if (err)				goto out;			fourth.__pad = (void __user *) &s;		}		need_back_translation =			(IPCOP_MASK (third) &			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;		if (need_back_translation)			fourth.__pad = (void __user *) &s;		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_semctl (first, second, third, fourth);		set_fs (old_fs);		if (need_back_translation) {			int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);			if (err2) err = -EFAULT;		}	} else {		struct semid_ds s;		struct semid_ds32 __user *usp = compat_ptr(pad);		mm_segment_t old_fs;		int need_back_translation;		if (third == IPC_SET) {			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);			if (err)				goto out;			fourth.__pad = (void __user *) &s;		}		need_back_translation =			(IPCOP_MASK (third) &			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;		if (need_back_translation)			fourth.__pad = (void __user *) &s;		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_semctl (first, second, third, fourth);		set_fs (old_fs);		if (need_back_translation) {			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);			err2 |= __put_user (s.sem_otime, &usp->sem_otime);			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);			if (err2) err = -EFAULT;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?