📄 sys_ia32.c
字号:
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); __put_user(0,name->sysname+__OLD_UTS_LEN); __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); __put_user(0,name->nodename+__OLD_UTS_LEN); __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); __put_user(0,name->release+__OLD_UTS_LEN); __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); __put_user(0,name->version+__OLD_UTS_LEN); { char *arch = (personality(current->personality) == PER_LINUX32) ? "i686" : "x86_64"; __copy_to_user(&name->machine,arch,strlen(arch)+1); } up_read(&uts_sem); error = error ? -EFAULT : 0; return error;}asmlinkage long sys32_uname(struct old_utsname * name){ int err; down_read(&uts_sem); err=copy_to_user(name, &system_utsname, sizeof (*name)); up_read(&uts_sem); if (personality(current->personality) == PER_LINUX32) err = copy_to_user(name->machine, "i686", 5); return err?-EFAULT:0;}extern int sys_ustat(dev_t, struct ustat *);asmlinkage long sys32_ustat(dev_t dev, struct ustat32 *u32p){ struct ustat u; mm_segment_t seg; int ret; seg = get_fs(); set_fs(KERNEL_DS); ret = sys_ustat(dev,&u); set_fs(seg); if (ret >= 0) { if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) || __put_user((__u32) u.f_tfree, &u32p->f_tfree) || __put_user((__u32) u.f_tinode, &u32p->f_tfree) || __copy_to_user(&u32p->f_fname, u.f_fname, sizeof(u.f_fname)) || __copy_to_user(&u32p->f_fpack, u.f_fpack, sizeof(u.f_fpack))) ret = -EFAULT; } return ret;} static int nargs(u32 src, char **dst) { int cnt; u32 val; cnt = 0; do { int ret = get_user(val, (__u32 *)(u64)src); if (ret) return ret; if (dst) dst[cnt] = (char *)(u64)val; cnt++; src += 4; if (cnt >= (MAX_ARG_PAGES*PAGE_SIZE)/sizeof(void*)) return -E2BIG; } while(val); if (dst) dst[cnt-1] = 0; return cnt; } asmlinkage long sys32_execve(char *name, u32 argv, u32 envp, struct pt_regs regs){ mm_segment_t oldseg; char **buf = NULL; int na = 0,ne = 0; int ret; unsigned sz = 0; if (argv) { na = nargs(argv, NULL); if (na < 0) return -EFAULT; } if (envp) { ne = nargs(envp, NULL); if (ne < 0) return -EFAULT; } if (argv || envp) { sz = (na+ne)*sizeof(void *); if (sz > PAGE_SIZE) buf = vmalloc(sz); else buf = kmalloc(sz, GFP_KERNEL); if (!buf) return -ENOMEM; } if (argv) { ret = nargs(argv, buf); if (ret < 0) goto free; } if (envp) { ret = nargs(envp, buf + na); if (ret < 0) goto free; } name = getname(name); ret = PTR_ERR(name); if (IS_ERR(name)) goto free; oldseg = get_fs(); set_fs(KERNEL_DS); ret = do_execve(name, argv ? buf : NULL, envp ? buf+na : NULL, ®s); set_fs(oldseg); if (ret == 0) current->ptrace &= ~PT_DTRACE; putname(name); free: if (argv || envp) { if (sz > PAGE_SIZE) vfree(buf); else kfree(buf); } return ret; } asmlinkage long sys32_fork(struct pt_regs regs){ return do_fork(SIGCHLD, regs.rsp, ®s, 0);}asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs){ if (!newsp) newsp = regs.rsp; return do_fork(clone_flags, newsp, ®s, 0);}/* * This is trivial, and on the face of it looks like it * could equally well be done in user mode. * * Not so, for quite unobvious reasons - register pressure. * In user mode vfork() cannot have a stack frame, and if * done by calling the "clone()" system call directly, you * do not have enough call-clobbered registers to hold all * the information you need. */asmlinkage long sys32_vfork(struct pt_regs regs){ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0);}/* * Some system calls that need sign extended arguments. This could be done by a generic wrapper. */ extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);asmlinkage long sys32_lseek (unsigned int fd, int offset, unsigned int whence){ return sys_lseek(fd, offset, whence);}extern int sys_kill(pid_t pid, int sig); asmlinkage long sys32_kill(int pid, int sig){ return sys_kill(pid, sig);} #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)/* Stuff for NFS server syscalls... */struct nfsctl_svc32 { u16 svc32_port; s32 svc32_nthreads;};struct nfsctl_client32 { s8 cl32_ident[NFSCLNT_IDMAX+1]; s32 cl32_naddr; struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX]; s32 cl32_fhkeytype; s32 cl32_fhkeylen; u8 cl32_fhkey[NFSCLNT_KEYMAX];};struct nfsctl_export32 { s8 ex32_client[NFSCLNT_IDMAX+1]; s8 ex32_path[NFS_MAXPATHLEN+1]; __kernel_dev_t32 ex32_dev; __kernel_ino_t32 ex32_ino; s32 ex32_flags; __kernel_uid_t32 ex32_anon_uid; __kernel_gid_t32 ex32_anon_gid;};struct nfsctl_uidmap32 { u32 ug32_ident; /* char * */ __kernel_uid_t32 ug32_uidbase; s32 ug32_uidlen; u32 ug32_udimap; /* uid_t * */ __kernel_uid_t32 ug32_gidbase; s32 ug32_gidlen; u32 ug32_gdimap; /* gid_t * */};struct nfsctl_fhparm32 { struct sockaddr gf32_addr; __kernel_dev_t32 gf32_dev; __kernel_ino_t32 gf32_ino; s32 gf32_version;};struct nfsctl_fdparm32 { struct sockaddr gd32_addr; s8 gd32_path[NFS_MAXPATHLEN+1]; s32 gd32_version;};struct nfsctl_fsparm32 { struct sockaddr gd32_addr; s8 gd32_path[NFS_MAXPATHLEN+1]; s32 gd32_maxlen;};struct nfsctl_arg32 { s32 ca32_version; /* safeguard */ union { struct nfsctl_svc32 u32_svc; struct nfsctl_client32 u32_client; struct nfsctl_export32 u32_export; struct nfsctl_uidmap32 u32_umap; struct nfsctl_fhparm32 u32_getfh; struct nfsctl_fdparm32 u32_getfd; struct nfsctl_fsparm32 u32_getfs; } u;#define ca32_svc u.u32_svc#define ca32_client u.u32_client#define ca32_export u.u32_export#define ca32_umap u.u32_umap#define ca32_getfh u.u32_getfh#define ca32_getfd u.u32_getfd#define ca32_getfs u.u32_getfs#define ca32_authd u.u32_authd};union nfsctl_res32 { __u8 cr32_getfh[NFS_FHSIZE]; struct knfsd_fh cr32_getfs;};static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port); err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads); return err;}static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= copy_from_user(&karg->ca_client.cl_ident[0], &arg32->ca32_client.cl32_ident[0], NFSCLNT_IDMAX); err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr); err |= copy_from_user(&karg->ca_client.cl_addrlist[0], &arg32->ca32_client.cl32_addrlist[0], (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); err |= __get_user(karg->ca_client.cl_fhkeytype, &arg32->ca32_client.cl32_fhkeytype); err |= __get_user(karg->ca_client.cl_fhkeylen, &arg32->ca32_client.cl32_fhkeylen); err |= copy_from_user(&karg->ca_client.cl_fhkey[0], &arg32->ca32_client.cl32_fhkey[0], NFSCLNT_KEYMAX); return err;}static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= copy_from_user(&karg->ca_export.ex_client[0], &arg32->ca32_export.ex32_client[0], NFSCLNT_IDMAX); err |= copy_from_user(&karg->ca_export.ex_path[0], &arg32->ca32_export.ex32_path[0], NFS_MAXPATHLEN); err |= __get_user(karg->ca_export.ex_dev, &arg32->ca32_export.ex32_dev); err |= __get_user(karg->ca_export.ex_ino, &arg32->ca32_export.ex32_ino); err |= __get_user(karg->ca_export.ex_flags, &arg32->ca32_export.ex32_flags); err |= __get_user(karg->ca_export.ex_anon_uid, &arg32->ca32_export.ex32_anon_uid); err |= __get_user(karg->ca_export.ex_anon_gid, &arg32->ca32_export.ex32_anon_gid); karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid); karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid); return err;}static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= copy_from_user(&karg->ca_getfh.gf_addr, &arg32->ca32_getfh.gf32_addr, (sizeof(struct sockaddr))); err |= __get_user(karg->ca_getfh.gf_dev, &arg32->ca32_getfh.gf32_dev); err |= __get_user(karg->ca_getfh.gf_ino, &arg32->ca32_getfh.gf32_ino); err |= __get_user(karg->ca_getfh.gf_version, &arg32->ca32_getfh.gf32_version); return err;}static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= copy_from_user(&karg->ca_getfd.gd_addr, &arg32->ca32_getfd.gd32_addr, (sizeof(struct sockaddr))); err |= copy_from_user(&karg->ca_getfd.gd_path, &arg32->ca32_getfd.gd32_path, (NFS_MAXPATHLEN+1)); err |= get_user(karg->ca_getfd.gd_version, &arg32->ca32_getfd.gd32_version); return err;}static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ int err; err = get_user(karg->ca_version, &arg32->ca32_version); err |= copy_from_user(&karg->ca_getfs.gd_addr, &arg32->ca32_getfs.gd32_addr, (sizeof(struct sockaddr))); err |= copy_from_user(&karg->ca_getfs.gd_path, &arg32->ca32_getfs.gd32_path, (NFS_MAXPATHLEN+1)); err |= get_user(karg->ca_getfs.gd_maxlen, &arg32->ca32_getfs.gd32_maxlen); return err;}/* This really doesn't need translations, we are only passing * back a union which contains opaque nfs file handle data. */static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32){ return copy_to_user(res32, kres, sizeof(*res32));}long asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32){ struct nfsctl_arg *karg = NULL; union nfsctl_res *kres = NULL; mm_segment_t oldfs; int err; karg = kmalloc(sizeof(*karg), GFP_USER); if(!karg) return -ENOMEM; if(res32) { kres = kmalloc(sizeof(*kres), GFP_USER); if(!kres) { kfree(karg); return -ENOMEM; } } switch(cmd) { case NFSCTL_SVC: err = nfs_svc32_trans(karg, arg32); break; case NFSCTL_ADDCLIENT: err = nfs_clnt32_trans(karg, arg32); break; case NFSCTL_DELCLIENT: err = nfs_clnt32_trans(karg, arg32); break; case NFSCTL_EXPORT: case NFSCTL_UNEXPORT: err = nfs_exp32_trans(karg, arg32); break; case NFSCTL_GETFH: err = nfs_getfh32_trans(karg, arg32); break; case NFSCTL_GETFD: err = nfs_getfd32_trans(karg, arg32); break; case NFSCTL_GETFS: err = nfs_getfs32_trans(karg, arg32); break; default: err = -EINVAL; break; } if(err) goto done; oldfs = get_fs(); set_fs(KERNEL_DS); err = sys_nfsservctl(cmd, karg, kres); set_fs(oldfs); if (err) goto done; if((cmd == NFSCTL_GETFH) || (cmd == NFSCTL_GETFD) || (cmd == NFSCTL_GETFS)) err = nfs_getfh32_res_trans(kres, res32);done: if(karg) { if(cmd == NFSCTL_UGIDUPDATE) { if(karg->ca_umap.ug_ident) kfree(karg->ca_umap.ug_ident); if(karg->ca_umap.ug_udimap) kfree(karg->ca_umap.ug_udimap); if(karg->ca_umap.ug_gdimap) kfree(karg->ca_umap.ug_gdimap); } kfree(karg); } if(kres) kfree(kres); return err;}#else /* !NFSD */extern asmlinkage long sys_ni_syscall(void);long asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2){ return sys_ni_syscall();}#endiflong sys32_module_warning(void){ static long warn_time = -(60*HZ); if (time_before(warn_time + 60*HZ,jiffies) && strcmp(current->comm,"klogd")) { printk(KERN_INFO "%s: 32bit modutils not supported on 64bit kernel\n", current->comm); warn_time = jiffies; } return -ENOSYS ;} long sys32_vm86_warning(void){ static long warn_time = -(60*HZ); if (time_before(warn_time + 60*HZ,jiffies)) { printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n", current->comm); warn_time = jiffies; } return -ENOSYS ;} /* This only triggers an i686 uname */struct exec_domain ia32_exec_domain = { name: "linux/uname-i686", pers_low: PER_LINUX32, pers_high: PER_LINUX32,}; static int __init ia32_init (void){ printk("IA32 emulation $Id: sys_ia32.c,v 1.54 2003/03/24 09:28:26 ak Exp $\n"); ia32_exec_domain.signal_map = default_exec_domain.signal_map; ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; register_exec_domain(&ia32_exec_domain); return 0;}__initcall(ia32_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -