📄 sys_ia32.c
字号:
{ struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); if ((iov = get_iovec32(vector, iovstack, &count, VERIFY_WRITE, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); set_fs(old_fs); if (iov != iovstack) kfree(iov); return ret;}asmlinkage longsys32_writev(int fd, struct iovec32 *vector, u32 count){ struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); if ((iov = get_iovec32(vector, iovstack, &count, VERIFY_READ, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); set_fs(old_fs); if (iov != iovstack) kfree(iov); return ret;}#define RLIM_INFINITY32 0xffffffff#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)struct rlimit32 { int rlim_cur; int rlim_max;};extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage longsys32_getrlimit(unsigned int resource, struct rlimit32 *rlim){ struct rlimit r; int ret; mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_getrlimit(resource, &r); set_fs(old_fs); if (!ret) { if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) || __put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur) || __put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max)) ret = -EFAULT; } return ret;}extern asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage longsys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim){ struct rlimit r; int ret; mm_segment_t old_fs; old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_old_getrlimit(resource, &r); set_fs(old_fs); if (!ret) { if (verify_area(VERIFY_WRITE, rlim, sizeof(struct rlimit32)) || __put_user(r.rlim_cur, &rlim->rlim_cur) || __put_user(r.rlim_max, &rlim->rlim_max)) ret = -EFAULT; } return ret;}extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage longsys32_setrlimit(unsigned int resource, struct rlimit32 *rlim){ struct rlimit r; int ret; mm_segment_t old_fs = get_fs (); if (resource >= RLIM_NLIMITS) return -EINVAL; if (verify_area(VERIFY_READ, rlim, sizeof(struct rlimit32)) || __get_user (r.rlim_cur, &rlim->rlim_cur) || __get_user (r.rlim_max, &rlim->rlim_max)) return -EFAULT; if (r.rlim_cur == RLIM_INFINITY32) r.rlim_cur = RLIM_INFINITY; if (r.rlim_max == RLIM_INFINITY32) r.rlim_max = RLIM_INFINITY; set_fs (KERNEL_DS); ret = sys_setrlimit(resource, &r); set_fs (old_fs); return ret;}/* * sys_time() can be implemented in user-level using * sys_gettimeofday(). x86-64 did this but i386 Linux did not * so we have to implement this system call here. */asmlinkage long sys32_time(int * tloc){ int i; /* SMP: This is fairly trivial. We grab CURRENT_TIME and stuff it to user space. No side effects */ i = CURRENT_TIME; if (tloc) { if (put_user(i,tloc)) i = -EFAULT; } return i;}struct rusage32 { struct timeval32 ru_utime; struct timeval32 ru_stime; int ru_maxrss; int ru_ixrss; int ru_idrss; int ru_isrss; int ru_minflt; int ru_majflt; int ru_nswap; int ru_inblock; int ru_oublock; int ru_msgsnd; int ru_msgrcv; int ru_nsignals; int ru_nvcsw; int ru_nivcsw;};static intput_rusage (struct rusage32 *ru, struct rusage *r){ if (verify_area(VERIFY_WRITE, ru, sizeof(struct rusage32)) || __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || __put_user (r->ru_maxrss, &ru->ru_maxrss) || __put_user (r->ru_ixrss, &ru->ru_ixrss) || __put_user (r->ru_idrss, &ru->ru_idrss) || __put_user (r->ru_isrss, &ru->ru_isrss) || __put_user (r->ru_minflt, &ru->ru_minflt) || __put_user (r->ru_majflt, &ru->ru_majflt) || __put_user (r->ru_nswap, &ru->ru_nswap) || __put_user (r->ru_inblock, &ru->ru_inblock) || __put_user (r->ru_oublock, &ru->ru_oublock) || __put_user (r->ru_msgsnd, &ru->ru_msgsnd) || __put_user (r->ru_msgrcv, &ru->ru_msgrcv) || __put_user (r->ru_nsignals, &ru->ru_nsignals) || __put_user (r->ru_nvcsw, &ru->ru_nvcsw) || __put_user (r->ru_nivcsw, &ru->ru_nivcsw)) return -EFAULT; return 0;}extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);asmlinkage longsys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru){ if (!ru) return sys_wait4(pid, stat_addr, options, NULL); else { struct rusage r; int ret; unsigned int status; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; if (stat_addr && put_user (status, stat_addr)) return -EFAULT; return ret; }}asmlinkage longsys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options){ return sys32_wait4(pid, stat_addr, options, NULL);}extern asmlinkage longsys_getrusage(int who, struct rusage *ru);asmlinkage longsys32_getrusage(int who, struct rusage32 *ru){ struct rusage r; int ret; mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_getrusage(who, &r); set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; return ret;}struct tms32 { __kernel_clock_t32 tms_utime; __kernel_clock_t32 tms_stime; __kernel_clock_t32 tms_cutime; __kernel_clock_t32 tms_cstime;};extern int sys_times(struct tms *); asmlinkage longsys32_times(struct tms32 *tbuf){ struct tms t; long ret; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); ret = sys_times(tbuf ? &t : NULL); set_fs (old_fs); if (tbuf) { if (verify_area(VERIFY_WRITE, tbuf, sizeof(struct tms32)) || __put_user (t.tms_utime, &tbuf->tms_utime) || __put_user (t.tms_stime, &tbuf->tms_stime) || __put_user (t.tms_cutime, &tbuf->tms_cutime) || __put_user (t.tms_cstime, &tbuf->tms_cstime)) return -EFAULT; } return ret;}static inline int get_flock(struct flock *kfl, struct flock32 *ufl){ int err; err = get_user(kfl->l_type, &ufl->l_type); err |= __get_user(kfl->l_whence, &ufl->l_whence); err |= __get_user(kfl->l_start, &ufl->l_start); err |= __get_user(kfl->l_len, &ufl->l_len); err |= __get_user(kfl->l_pid, &ufl->l_pid); return err;}static inline int put_flock(struct flock *kfl, struct flock32 *ufl){ int err; err = __put_user(kfl->l_type, &ufl->l_type); err |= __put_user(kfl->l_whence, &ufl->l_whence); err |= __put_user(kfl->l_start, &ufl->l_start); err |= __put_user(kfl->l_len, &ufl->l_len); err |= __put_user(kfl->l_pid, &ufl->l_pid); return err;}extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg){ switch (cmd) { case F_GETLK: case F_SETLK: case F_SETLKW: { struct flock f; mm_segment_t old_fs; long ret; if (get_flock(&f, (struct flock32 *)arg)) return -EFAULT; old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs (old_fs); if (ret) return ret; if (put_flock(&f, (struct flock32 *)arg)) return -EFAULT; return 0; } case F_GETLK64: case F_SETLK64: case F_SETLKW64: return sys32_fcntl64(fd,cmd,arg); default: return sys_fcntl(fd, cmd, (unsigned long)arg); }}static inline int get_flock64(struct ia32_flock64 *fl32, struct flock *fl64){ if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) { int ret = __get_user(fl64->l_type, &fl32->l_type); ret |= __get_user(fl64->l_whence, &fl32->l_whence); ret |= __get_user(fl64->l_start, &fl32->l_start); ret |= __get_user(fl64->l_len, &fl32->l_len); ret |= __get_user(fl64->l_pid, &fl32->l_pid); return ret; } return -EFAULT; }static inline int put_flock64(struct ia32_flock64 *fl32, struct flock *fl64){ if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) { int ret = __put_user(fl64->l_type, &fl32->l_type); ret |= __put_user(fl64->l_whence, &fl32->l_whence); ret |= __put_user(fl64->l_start, &fl32->l_start); ret |= __put_user(fl64->l_len, &fl32->l_len); ret |= __put_user(fl64->l_pid, &fl32->l_pid); return ret; } return -EFAULT; }asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg){ struct flock fl64; mm_segment_t oldfs = get_fs(); int ret = 0; int oldcmd = cmd; unsigned long oldarg = arg; switch (cmd) { case F_GETLK64: cmd = F_GETLK; goto cnv; case F_SETLK64: cmd = F_SETLK; goto cnv; case F_SETLKW64: cmd = F_SETLKW; cnv: ret = get_flock64((struct ia32_flock64 *)arg, &fl64); arg = (unsigned long)&fl64; set_fs(KERNEL_DS); break; case F_GETLK: case F_SETLK: case F_SETLKW: return sys32_fcntl(fd,cmd,arg); } if (!ret) ret = sys_fcntl(fd, cmd, arg); set_fs(oldfs); if (oldcmd == F_GETLK64 && !ret) ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64); return ret; }asmlinkage long sys32_ni_syscall(int call){ printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", call, current->comm); return -ENOSYS; } /* 32-bit timeval and related flotsam. */extern asmlinkage long sys_utime(char * filename, struct utimbuf * times);struct utimbuf32 { __kernel_time_t32 actime, modtime;};asmlinkage longsys32_utime(char * filename, struct utimbuf32 *times){ struct utimbuf t; mm_segment_t old_fs; int ret; char *filenam; if (!times) return sys_utime(filename, NULL); if (verify_area(VERIFY_READ, times, sizeof(struct utimbuf32)) || __get_user (t.actime, ×->actime) || __get_user (t.modtime, ×->modtime)) return -EFAULT; filenam = getname (filename); ret = PTR_ERR(filenam); if (!IS_ERR(filenam)) { old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_utime(filenam, &t); set_fs (old_fs); putname(filenam); } return ret;}extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2);asmlinkage longsys32_sysfs(int option, u32 arg1, u32 arg2){ return sys_sysfs(option, arg1, arg2);}extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data);static char *badfs[] = { "smbfs", "ncpfs", NULL}; static int checktype(char *user_type) { int err = 0; char **s,*kernel_type = getname(user_type); if (!kernel_type || IS_ERR(kernel_type)) return -EFAULT; for (s = badfs; *s; ++s) if (!strcmp(kernel_type, *s)) { printk(KERN_ERR "mount32: unsupported fs `%s' -- use 64bit mount\n", *s); err = -EINVAL; break; } putname(user_type); return err;} asmlinkage longsys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data){ int err; if(!capable(CAP_SYS_ADMIN)) return -EPERM; err = checktype(type); if (err) return err; return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data));}struct sysinfo32 { s32 uptime; u32 loads[3]; u32 totalram; u32 freeram; u32 sharedram; u32 bufferram; u32 totalswap; u32 freeswap; unsigned short procs; char _f[22];};extern asmlinkage long sys_sysinfo(struct sysinfo *info);asmlinkage longsys32_sysinfo(struct sysinfo32 *info){ struct sysinfo s; int ret; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); ret = sys_sysinfo(&s); set_fs (old_fs); if (verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo32)) || __put_user (s.uptime, &info->uptime) || __put_user (s.loads[0], &info->loads[0]) || __put_user (s.loads[1], &info->loads[1]) || __put_user (s.loads[2], &info->loads[2]) || __put_user (s.totalram, &info->totalram) || __put_user (s.freeram, &info->freeram) || __put_user (s.sharedram, &info->sharedram) || __put_user (s.bufferram, &info->bufferram) || __put_user (s.totalswap, &info->totalswap) || __put_user (s.freeswap, &info->freeswap) || __put_user (s.procs, &info->procs)) return -EFAULT; return 0;} extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);asmlinkage longsys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval){ struct timespec t; int ret; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); ret = sys_sched_rr_get_interval(pid, &t);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -