📄 sys_ppc32.c
字号:
|| __put_user(space, vals+1)) return -EFAULT; strings += len; bufsize -= len; space += len; } if (put_user(i, ret)) return -EFAULT; else return 0;calc_space_needed: for (; i < mod->nsyms; ++i, ++s) space += strlen(s->name)+1; if (put_user(space, ret)) return -EFAULT; else return -ENOSPC;}static inline intqm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret){ int error = 0; if (mod->next == NULL) return -EINVAL; if (sizeof(struct module_info32) <= bufsize) { struct module_info32 info; info.addr = (unsigned long)mod; info.size = mod->size; info.flags = mod->flags; info.usecount = ((mod_member_present(mod, can_unload) && mod->can_unload) ? -1 : atomic_read(&mod->uc.usecount)); if (copy_to_user(buf, &info, sizeof(struct module_info32))) return -EFAULT; } else error = -ENOSPC; if (put_user(sizeof(struct module_info32), ret)) return -EFAULT; return error;}/* Note: it is necessary to treat which as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */asmlinkage long sys32_query_module(char *name_user, u32 which, char *buf, __kernel_size_t32 bufsize, u32 ret){ struct module *mod; int err; PPCDBG(PPCDBG_SYS32M, "sys32_query_module - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); lock_kernel(); if (name_user == 0) { /* This finds "kernel_module" which is not exported. */ for(mod = module_list; mod->next != NULL; mod = mod->next) ; } else { long namelen; char *name; if ((namelen = get_mod_name(name_user, &name)) < 0) { err = namelen; goto out; } err = -ENOENT; if (namelen == 0) { /* This finds "kernel_module" which is not exported. */ for(mod = module_list; mod->next != NULL; mod = mod->next) ; } else if ((mod = find_module(name)) == NULL) { put_mod_name(name); goto out; } put_mod_name(name); } switch ((int)which) { case 0: err = 0; break; case QM_MODULES: err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_DEPS: err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_REFS: err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_SYMBOLS: err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; case QM_INFO: err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret)); break; default: err = -EINVAL; break; }out: unlock_kernel(); PPCDBG(PPCDBG_SYS32, "sys32_query_module - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); return err;}struct kernel_sym32 { u32 value; char name[60];}; extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);asmlinkage long sys32_get_kernel_syms(struct kernel_sym32 *table){ int len, i; struct kernel_sym *tbl; mm_segment_t old_fs; PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - entered - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); len = sys_get_kernel_syms(NULL); if (!table) return len; tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL); if (!tbl) return -ENOMEM; old_fs = get_fs(); set_fs (KERNEL_DS); sys_get_kernel_syms(tbl); set_fs (old_fs); for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) { if (put_user (tbl[i].value, &table->value) || copy_to_user (table->name, tbl[i].name, 60)) break; } kfree (tbl); PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - exited - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm); return i;}#else /* CONFIG_MODULES */asmlinkage unsigned long sys32_create_module(const char *name_user, size_t size){ PPCDBG(PPCDBG_SYS32, "sys32_create_module - running - pid=%ld, comm=%s\n", current->pid, current->comm); return -ENOSYS;}asmlinkage long sys32_init_module(const char *name_user, struct module *mod_user){ PPCDBG(PPCDBG_SYS32, "sys32_init_module - running - pid=%ld, comm=%s\n", current->pid, current->comm); return -ENOSYS;}asmlinkage long sys32_delete_module(const char *name_user){ PPCDBG(PPCDBG_SYS32, "sys32_delete_module - running - pid=%ld, comm=%s\n", current->pid, current->comm); return -ENOSYS;}/* Note: it is necessary to treat which as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */asmlinkage long sys32_query_module(const char *name_user, u32 which, char *buf, size_t bufsize, size_t *ret){ PPCDBG(PPCDBG_SYS32, "sys32_query_module - entered - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); /* Let the program know about the new interface. Not that it'll do them much good. */ if ((int)which == 0) return 0; PPCDBG(PPCDBG_SYS32, "sys32_query_module - exited - pid=%ld current=%lx comm=%s\n", current->pid, current, current->comm); return -ENOSYS;}asmlinkage long sys32_get_kernel_syms(struct kernel_sym *table){ PPCDBG(PPCDBG_SYS32, "sys32_get_kernel_syms - running - pid=%ld, comm=%s\n", current->pid, current->comm); return -ENOSYS;}#endif /* CONFIG_MODULES *//* 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); if(err) return -EFAULT; return 0;}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 = karg->ca_export.ex_anon_uid; karg->ca_export.ex_anon_gid = karg->ca_export.ex_anon_gid; if(err) return -EFAULT; return 0;}static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32){ u32 uaddr; int i; int err; memset(karg, 0, sizeof(*karg)); if(__get_user(karg->ca_version, &arg32->ca32_version)) return -EFAULT; karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER); if(!karg->ca_umap.ug_ident) return -ENOMEM; err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident); if(strncpy_from_user(karg->ca_umap.ug_ident, (char *)A(uaddr), PAGE_SIZE) <= 0) return -EFAULT; err |= __get_user(karg->ca_umap.ug_uidbase, &arg32->ca32_umap.ug32_uidbase); err |= __get_user(karg->ca_umap.ug_uidlen, &arg32->ca32_umap.ug32_uidlen); err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap); if (err) return -EFAULT; karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen), GFP_USER); if(!karg->ca_umap.ug_udimap) return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_uidlen; i++) err |= __get_user(karg->ca_umap.ug_udimap[i], &(((__kernel_uid_t32 *)A(uaddr))[i])); err |= __get_user(karg->ca_umap.ug_gidbase, &arg32->ca32_umap.ug32_gidbase); err |= __get_user(karg->ca_umap.ug_uidlen, &arg32->ca32_umap.ug32_gidlen); err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap); if (err) return -EFAULT; karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen), GFP_USER); if(!karg->ca_umap.ug_gdimap) return -ENOMEM; for(i = 0; i < karg->ca_umap.ug_gidlen; i++) err |= __get_user(karg->ca_umap.ug_gdimap[i], &(((__kernel_gid_t32 *)A(uaddr))[i])); 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); if(err) return -EFAULT; return 0;}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); if(err) return -EFAULT; return 0;}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); if(err) return -EFAULT; return 0;}/* 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){ int err; err = copy_to_user(res32, kres, sizeof(*res32)); if(err) return -EFAULT; return 0;}/* Note: it is necessary to treat cmd_parm as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */int asmlinkage sys32_nfsservctl(u32 cmd_parm, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32){ int cmd = (int)cmd_parm; 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -