⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_sparc32.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: sys_sparc32.c,v 1.171 2000/12/13 16:34:55 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/utime.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/malloc.h>#include <linux/uio.h>#include <linux/nfs_fs.h>#include <linux/smb_fs.h>#include <linux/smb_mount.h>#include <linux/ncp_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/sysctl.h>#include <asm/types.h>#include <asm/ipc.h>#include <asm/uaccess.h>#include <asm/fpumacro.h>#include <asm/semaphore.h>#include <net/scm.h>/* Use this to get at 32-bit user passed pointers. *//* Things to consider: the low-level assembly stub does   srl x, 0, x for first four arguments, so if you have   pointer to something in the first four arguments, just   declare it as a pointer, not u32. On the other side,    arguments from 5th onwards should be declared as u32   for pointers, and need AA() around each usage.   A() macro should be used for places where you e.g.   have some internal variable u32 and just want to get   rid of a compiler warning. AA() has to be used in   places where you want to convert a function argument   to 32bit pointer or when you e.g. access pt_regs   structure and want to consider 32bit registers only.   -jj */#define A(__x) ((unsigned long)(__x))#define AA(__x)				\({	unsigned long __ret;		\	__asm__ ("srl	%0, 0, %0"	\		 : "=r" (__ret)		\		 : "0" (__x));		\	__ret;				\})extern asmlinkage long sys_chown(const char *, uid_t,gid_t);extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);extern asmlinkage long sys_setregid(gid_t, gid_t);extern asmlinkage long sys_setgid(gid_t);extern asmlinkage long sys_setreuid(uid_t, uid_t);extern asmlinkage long sys_setuid(uid_t);extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);extern asmlinkage long sys_setfsuid(uid_t);extern asmlinkage long sys_setfsgid(gid_t); /* For this source file, we want overflow handling. */#undef high2lowuid#undef high2lowgid#undef low2highuid#undef low2highgid#undef SET_UID16#undef SET_GID16#undef NEW_TO_OLD_UID#undef NEW_TO_OLD_GID#undef SET_OLDSTAT_UID#undef SET_OLDSTAT_GID#undef SET_STAT_UID#undef SET_STAT_GID#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)#define SET_UID16(var, uid)	var = high2lowuid(uid)#define SET_GID16(var, gid)	var = high2lowgid(gid)#define NEW_TO_OLD_UID(uid)	high2lowuid(uid)#define NEW_TO_OLD_GID(gid)	high2lowgid(gid)#define SET_OLDSTAT_UID(stat, uid)	(stat).st_uid = high2lowuid(uid)#define SET_OLDSTAT_GID(stat, gid)	(stat).st_gid = high2lowgid(gid)#define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)#define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group){	return sys_chown(filename, low2highuid(user), low2highgid(group));}asmlinkage long sys32_lchown16(const char * 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 *ruid, u16 *euid, u16 *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 *rgid, u16 *egid, u16 *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);}asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist){	u16 groups[NGROUPS];	int i,j;	if (gidsetsize < 0)		return -EINVAL;	i = current->ngroups;	if (gidsetsize) {		if (i > gidsetsize)			return -EINVAL;		for(j=0;j<i;j++)			groups[j] = current->groups[j];		if (copy_to_user(grouplist, groups, sizeof(u16)*i))			return -EFAULT;	}	return i;}asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist){	u16 groups[NGROUPS];	int i;	if (!capable(CAP_SETGID))		return -EPERM;	if ((unsigned) gidsetsize > NGROUPS)		return -EINVAL;	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))		return -EFAULT;	for (i = 0 ; i < gidsetsize ; i++)		current->groups[i] = (gid_t)groups[i];	current->ngroups = gidsetsize;	return 0;}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.  */struct timeval32{    int tv_sec, tv_usec;};struct itimerval32{    struct timeval32 it_interval;    struct timeval32 it_value;};static inline long get_tv32(struct timeval *o, struct timeval32 *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 timeval32 *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)));}static inline long get_it32(struct itimerval *o, struct itimerval32 *i){	return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));}static inline long put_it32(struct itimerval32 *o, struct itimerval *i){	return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));}extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);asmlinkage int sys32_ioperm(u32 from, u32 num, int on){	return sys_ioperm((unsigned long)from, (unsigned long)num, on);}struct msgbuf32 { s32 mtype; char mtext[1]; };struct ipc_perm32{	key_t    	  key;        __kernel_uid_t32  uid;        __kernel_gid_t32  gid;        __kernel_uid_t32  cuid;        __kernel_gid_t32  cgid;        __kernel_mode_t32 mode;        unsigned short  seq;};struct semid_ds32 {        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */        __kernel_time_t32 sem_otime;              /* last semop time */        __kernel_time_t32 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;	__kernel_time_t32 sem_otime;	unsigned int	  __pad2;	__kernel_time_t32 sem_ctime;	u32 sem_nsems;	u32 __unused1;	u32 __unused2;};struct msqid_ds32{        struct ipc_perm32 msg_perm;        u32 msg_first;        u32 msg_last;        __kernel_time_t32 msg_stime;        __kernel_time_t32 msg_rtime;        __kernel_time_t32 msg_ctime;        u32 wwait;        u32 rwait;        unsigned short msg_cbytes;        unsigned short msg_qnum;          unsigned short msg_qbytes;        __kernel_ipc_pid_t32 msg_lspid;        __kernel_ipc_pid_t32 msg_lrpid;};struct msqid64_ds32 {	struct ipc64_perm msg_perm;	unsigned int   __pad1;	__kernel_time_t32 msg_stime;	unsigned int   __pad2;	__kernel_time_t32 msg_rtime;	unsigned int   __pad3;	__kernel_time_t32 msg_ctime;	unsigned int  msg_cbytes;	unsigned int  msg_qnum;	unsigned int  msg_qbytes;	__kernel_pid_t32 msg_lspid;	__kernel_pid_t32 msg_lrpid;	unsigned int  __unused1;	unsigned int  __unused2;};struct shmid_ds32 {	struct ipc_perm32       shm_perm;	int                     shm_segsz;	__kernel_time_t32       shm_atime;	__kernel_time_t32       shm_dtime;	__kernel_time_t32       shm_ctime;	__kernel_ipc_pid_t32    shm_cpid; 	__kernel_ipc_pid_t32    shm_lpid; 	unsigned short          shm_nattch;};struct shmid64_ds32 {	struct ipc64_perm	shm_perm;	unsigned int		__pad1;	__kernel_time_t32	shm_atime;	unsigned int		__pad2;	__kernel_time_t32	shm_dtime;	unsigned int		__pad3;	__kernel_time_t32	shm_ctime;	__kernel_size_t32	shm_segsz;	__kernel_pid_t32	shm_cpid;	__kernel_pid_t32	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))static int do_sys32_semctl(int first, int second, int third, void *uptr){	union semun fourth;	u32 pad;	int err = -EINVAL;	if (!uptr)		goto out;	err = -EFAULT;	if (get_user (pad, (u32 *)uptr))		goto out;	if(third == SETVAL)		fourth.val = (int)pad;	else		fourth.__pad = (void *)A(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 *usp = (struct semid64_ds32 *)A(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 = &s;		}		need_back_translation =			(IPCOP_MASK (third) &			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;		if (need_back_translation)			fourth.__pad = &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 *usp = (struct semid_ds32 *)A(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 = &s;		}		need_back_translation =			(IPCOP_MASK (third) &			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;		if (need_back_translation)			fourth.__pad = &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);

⌨️ 快捷键说明

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