📄 sys_parisc32.c
字号:
asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim){ struct rlimit32 rlim32; struct rlimit new_rlim, *old_rlim; if (resource >= RLIM_NLIMITS) return -EINVAL; if (copy_from_user(&rlim32, rlim, sizeof(rlim))) return -EFAULT; if (rlim32.rlim_cur == RLIM32_INFINITY) { new_rlim.rlim_cur = RLIM_INFINITY; } else { new_rlim.rlim_cur = rlim32.rlim_cur; } if (rlim32.rlim_max == RLIM32_INFINITY) { new_rlim.rlim_max = RLIM_INFINITY; } else { new_rlim.rlim_max = rlim32.rlim_max; } old_rlim = current->rlim + resource; if (((new_rlim.rlim_cur > old_rlim->rlim_max) || (new_rlim.rlim_max > old_rlim->rlim_max)) && !capable(CAP_SYS_RESOURCE)) return -EPERM; if (resource == RLIMIT_NOFILE) { if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) return -EPERM; } if (resource == RLIMIT_STACK) { if (new_rlim.rlim_max > 1024 * 1024 * 1024) { new_rlim.rlim_max = 1024 * 1024 * 1024; } new_rlim.rlim_max = PAGE_ALIGN(new_rlim.rlim_max); } *old_rlim = new_rlim; return 0;}static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel){ int i; unsigned long page; struct vm_area_struct *vma; *kernel = 0; if(!user) return 0; vma = find_vma(current->mm, (unsigned long)user); if(!vma || (unsigned long)user < vma->vm_start) return -EFAULT; if(!(vma->vm_flags & VM_READ)) return -EFAULT; i = vma->vm_end - (unsigned long) user; if(PAGE_SIZE <= (unsigned long) i) i = PAGE_SIZE - 1; if(!(page = __get_free_page(GFP_KERNEL))) return -ENOMEM; if(copy_from_user((void *) page, user, i)) { free_page(page); return -EFAULT; } *kernel = page; return 0;}#define SMBFS_NAME "smbfs"#define NCPFS_NAME "ncpfs"asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data){ unsigned long type_page = 0; unsigned long data_page = 0; unsigned long dev_page = 0; unsigned long dir_page = 0; int err, is_smb, is_ncp; is_smb = is_ncp = 0; err = copy_mount_stuff_to_kernel((const void *)type, &type_page); if (err) goto out; if (!type_page) { err = -EINVAL; goto out; } is_smb = !strcmp((char *)type_page, SMBFS_NAME); is_ncp = !strcmp((char *)type_page, NCPFS_NAME); err = copy_mount_stuff_to_kernel((const void *)(unsigned long)data, &data_page); if (err) goto type_out; err = copy_mount_stuff_to_kernel(dev_name, &dev_page); if (err) goto data_out; err = copy_mount_stuff_to_kernel(dir_name, &dir_page); if (err) goto dev_out; if (!is_smb && !is_ncp) { lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); unlock_kernel(); } else { if (is_ncp) panic("NCP mounts not yet supported 32/64 parisc"); /* do_ncp_super_data_conv((void *)data_page); */ else { panic("SMB mounts not yet supported 32/64 parisc"); /* do_smb_super_data_conv((void *)data_page); */ } lock_kernel(); err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); unlock_kernel(); } free_page(dir_page);dev_out: free_page(dev_page);data_out: free_page(data_page);type_out: free_page(type_page);out: return err;}#ifdef CONFIG_MODULESstruct module_info32 { u32 addr; u32 size; u32 flags; s32 usecount;};/* Query various bits about modules. */static inline longget_mod_name(const char *user_name, char **buf){ unsigned long page; long retval; if ((unsigned long)user_name >= TASK_SIZE && !segment_eq(get_fs (), KERNEL_DS)) return -EFAULT; page = __get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE); if (retval > 0) { if (retval < PAGE_SIZE) { *buf = (char *)page; return retval; } retval = -ENAMETOOLONG; } else if (!retval) retval = -EINVAL; free_page(page); return retval;}static inline voidput_mod_name(char *buf){ free_page((unsigned long)buf);}static __inline__ struct module *find_module(const char *name){ struct module *mod; for (mod = module_list; mod ; mod = mod->next) { if (mod->flags & MOD_DELETED) continue; if (!strcmp(mod->name, name)) break; } return mod;}static intqm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret){ struct module *mod; size_t nmod, space, len; nmod = space = 0; for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) { len = strlen(mod->name)+1; if (len > bufsize) goto calc_space_needed; if (copy_to_user(buf, mod->name, len)) return -EFAULT; buf += len; bufsize -= len; space += len; } if (put_user(nmod, ret)) return -EFAULT; else return 0;calc_space_needed: space += len; while ((mod = mod->next)->next != NULL) space += strlen(mod->name)+1; if (put_user(space, ret)) return -EFAULT; else return -ENOSPC;}static intqm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret){ size_t i, space, len; if (mod->next == NULL) return -EINVAL; if (!MOD_CAN_QUERY(mod)) return put_user(0, ret); space = 0; for (i = 0; i < mod->ndeps; ++i) { const char *dep_name = mod->deps[i].dep->name; len = strlen(dep_name)+1; if (len > bufsize) goto calc_space_needed; if (copy_to_user(buf, dep_name, len)) return -EFAULT; buf += len; bufsize -= len; space += len; } return put_user(i, ret);calc_space_needed: space += len; while (++i < mod->ndeps) space += strlen(mod->deps[i].dep->name)+1; if (put_user(space, ret)) return -EFAULT; else return -ENOSPC;}static intqm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret){ size_t nrefs, space, len; struct module_ref *ref; if (mod->next == NULL) return -EINVAL; if (!MOD_CAN_QUERY(mod)) if (put_user(0, ret)) return -EFAULT; else return 0; space = 0; for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) { const char *ref_name = ref->ref->name; len = strlen(ref_name)+1; if (len > bufsize) goto calc_space_needed; if (copy_to_user(buf, ref_name, len)) return -EFAULT; buf += len; bufsize -= len; space += len; } if (put_user(nrefs, ret)) return -EFAULT; else return 0;calc_space_needed: space += len; while ((ref = ref->next_ref) != NULL) space += strlen(ref->ref->name)+1; if (put_user(space, ret)) return -EFAULT; else return -ENOSPC;}static inline intqm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret){ size_t i, space, len; struct module_symbol *s; char *strings; unsigned *vals; if (!MOD_CAN_QUERY(mod)) if (put_user(0, ret)) return -EFAULT; else return 0; space = mod->nsyms * 2*sizeof(u32); i = len = 0; s = mod->syms; if (space > bufsize) goto calc_space_needed; if (!access_ok(VERIFY_WRITE, buf, space)) return -EFAULT; bufsize -= space; vals = (unsigned *)buf; strings = buf+space; for (; i < mod->nsyms ; ++i, ++s, vals += 2) { len = strlen(s->name)+1; if (len > bufsize) goto calc_space_needed; if (copy_to_user(strings, s->name, len) || __put_user(s->value, vals+0) || __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;}asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, __kernel_size_t32 *ret){ struct module *mod; int err; 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 (which) { case 0: err = 0; break; case QM_MODULES: err = qm_modules(buf, bufsize, ret); break; case QM_DEPS: err = qm_deps(mod, buf, bufsize, ret); break; case QM_REFS: err = qm_refs(mod, buf, bufsize, ret); break; case QM_SYMBOLS: err = qm_symbols(mod, buf, bufsize, ret); break; case QM_INFO: err = qm_info(mod, buf, bufsize, ret); break; default: err = -EINVAL; break; }out: unlock_kernel(); return err;}struct kernel_sym32 { u32 value; char name[60];}; extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table){ int len, i; struct kernel_sym *tbl; mm_segment_t old_fs; 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++) { if (put_user (tbl[i].value, &table->value) || copy_to_user (table->name, tbl[i].name, 60)) break; } kfree (tbl); return i;}#else /* CONFIG_MODULES */asmlinkage intsys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret){ /* Let the program know about the new interface. Not that it'll do them much good. */ if (which == 0) return 0; return -ENOSYS;}asmlinkage intsys32_get_kernel_syms(struct kernel_sym *table){ return -ENOSYS;}#endif /* CONFIG_MODULES *//* readv/writev stolen from mips64 */struct iovec32 { unsigned int iov_base; int iov_len; };typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);static longdo_readv_writev32(int type, struct file *file, const struct iovec32 *vector, u32 count){ unsigned long tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack, *ivp; struct inode *inode; long retval, i; IO_fn_t fn; /* First get the "struct iovec" from user memory and * verify all the pointers */ if (!count) return 0; if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; if (count > UIO_FASTIOV) { iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); if (!iov) return -ENOMEM; } tot_len = 0; i = count; ivp = iov; while (i > 0) { u32 len; u32 buf; __get_user(len, &vector->iov_len); __get_user(buf, &vector->iov_base); tot_len += len; ivp->iov_base = (void *)A(buf); ivp->iov_len = (__kernel_size_t) len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -