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 + -
显示快捷键?