| #include "linux/types.h" |
| #include "linux/utsname.h" |
| #include "linux/utime.h" |
| #include "linux/mm.h" |
| #include "linux/unistd.h" |
| #include "linux/smp_lock.h" |
| #include "linux/file.h" |
| #include "linux/poll.h" |
| #include "linux/module.h" |
| #include "linux/msg.h" |
| #include "linux/shm.h" |
| #include "linux/spinlock.h" |
| #include "asm/segment.h" |
| #include "asm/mman.h" |
| #include "asm/uaccess.h" |
| #include "asm/ipc.h" |
| #include "kern.h" |
| #include "user_util.h" |
| #include "kern_util.h" |
| |
| extern int sys_getpid(void); |
| extern int sys_getppid(void); |
| extern long sys_open(const char * filename,int flags,int mode); |
| extern int sys_getuid(void); |
| extern int sys_geteuid(void); |
| extern int sys_getgid(void); |
| extern int sys_getegid(void); |
| extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); |
| extern int sys_reboot(int magic, int magic_too, int flag); |
| extern int do_sigaction(int sig, const struct k_sigaction *act, |
| struct k_sigaction *oact); |
| extern unsigned long sys_brk(unsigned long brk); |
| extern int sys_time(int * tloc); |
| extern int sys_socketcall(int call, unsigned long *args); |
| extern long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); |
| extern int sys_setsid(void); |
| extern int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset); |
| extern int sys_newlstat(char * filename, struct stat * statbuf); |
| extern int sys_newfstat(unsigned int fd, struct stat * statbuf); |
| extern int sys_unlink(const char * pathname); |
| extern int sys_write(unsigned int fd,char * buf,unsigned int count); |
| extern int sys_gettimeofday(struct timeval *tv, struct timezone *tz); |
| extern int sys_read(unsigned int fd, char * buf, int count); |
| extern int sys_access(const char * filename, int mode); |
| extern int sys_munmap(unsigned long addr, size_t len); |
| extern int do_fork(unsigned long clone_flags, unsigned long usp, |
| struct pt_regs *regs); |
| extern int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, |
| struct rusage * ru); |
| extern int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); |
| extern int sys_dup(unsigned int fildes); |
| extern int sys_exit(int error_code); |
| extern int sys_execve(char *file, char **argv, char **env); |
| extern long sys_lseek(unsigned int fd, off_t offset, unsigned int origin); |
| extern int sys_dup2(unsigned int oldfd, unsigned int newfd); |
| extern int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, |
| struct timeval *tvp); |
| extern int sys_mprotect(unsigned long start, size_t len, unsigned long prot); |
| extern int sys_newuname(struct new_utsname * name); |
| extern int sys_getppid(void); |
| extern int sys_newstat(char * filename, struct stat * statbuf); |
| extern int sys_getpgrp(void); |
| extern int sys_sethostname(char *name, int len); |
| extern int sys_getrusage(int who, struct rusage *ru); |
| extern int sys_setdomainname(char *name, int len); |
| extern int sys_sync(void); |
| extern int sys_llseek(unsigned int fd, unsigned long offset_high, |
| unsigned long offset_low, loff_t * result, |
| unsigned int origin); |
| extern int sys_readlink(const char * path, char * buf, int bufsiz); |
| extern int sys_mount(char * dev_name, char * dir_name, char * type, |
| unsigned long new_flags, void * data); |
| extern int sys_utime(char * filename, struct utimbuf * times); |
| extern int sys_getdents(unsigned int fd, void * dirent, unsigned int count); |
| extern int sys_ftruncate(unsigned int fd, unsigned long length); |
| extern int sys_syslog(int type, char * buf, int len); |
| extern int sys_chdir(const char * filename); |
| extern int sys_getrlimit(unsigned int resource, struct rlimit *rlim); |
| extern int sys_setrlimit(unsigned int resource, struct rlimit *rlim); |
| extern int sys_getpriority(int which, int who); |
| extern int sys_setpriority(int which, int who, int niceval); |
| extern int sys_getgroups(int gidsetsize, gid_t *grouplist); |
| extern int sys_setgroups(int gidsetsize, gid_t *grouplist); |
| extern int sys_umask(int mask); |
| extern int sys_chmod(const char * filename, mode_t mode); |
| extern int sys_chown(const char * filename, uid_t user, gid_t group); |
| extern unsigned int sys_alarm(unsigned int seconds); |
| extern int sys_flock(unsigned int fd, unsigned int cmd); |
| extern int sys_vhangup(void); |
| extern int sys_bdflush(int func, long data); |
| extern int sys_setpgid(pid_t pid, pid_t pgid); |
| extern int sys_setuid(uid_t uid); |
| extern int sys_setreuid(uid_t ruid, uid_t euid); |
| extern int sys_setregid(gid_t rgid, gid_t egid); |
| extern int sys_setgid(gid_t gid); |
| extern int sys_statfs(const char * path, struct statfs * buf); |
| extern int sys_lchown(const char * filename, uid_t user, gid_t group); |
| extern int sys_kill(int pid, int sig); |
| extern int sys_rt_sigaction(int sig, const struct sigaction *act, |
| struct sigaction *oact, size_t sigsetsize); |
| extern int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, |
| size_t sigsetsize); |
| extern int sys_getcwd(char *buf, unsigned long size); |
| extern int sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout); |
| extern int sys_link(const char * oldname, const char * newname); |
| extern ssize_t sys_writev(unsigned long fd, const struct iovec * vector, |
| unsigned long count); |
| extern int sys_fsync(unsigned int fd); |
| extern int sys_get_kernel_syms(struct kernel_sym *table); |
| extern int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); |
| extern int sys_fstatfs(unsigned int fd, struct statfs * buf); |
| extern int sys_delete_module(const char *name_user); |
| extern int sys_fchdir(unsigned int fd); |
| extern int sys_mkdir(const char * pathname, int mode); |
| extern int sys_rmdir(const char * pathname); |
| extern int sys_rename(const char * oldname, const char * newname); |
| extern int sys_mknod(const char * filename, int mode, dev_t dev); |
| extern int sys_umount(char * name, int flags); |
| extern int sys_fchmod(unsigned int fd, mode_t mode); |
| extern long sys_quotactl(int cmd, const char *special, int id, caddr_t addr); |
| extern int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize); |
| extern long sys_setfsuid(uid_t uid); |
| extern long sys_setfsgid(gid_t gid); |
| extern long sys_swapon(const char * specialfile, int swap_flags); |
| extern long sys_swapoff(const char * specialfile); |
| extern long sys_symlink(const char *oldname, const char *newname); |
| extern long sys_oldumount(char * name); |
| extern long sys_fchown(unsigned int fd, uid_t user, gid_t group); |
| extern long sys_getpgid(pid_t pid); |
| extern unsigned long sys_mremap(unsigned long addr, |
| unsigned long old_len, unsigned long new_len, |
| unsigned long flags, unsigned long new_addr); |
| extern long sys_msync(unsigned long start, size_t len, int flags); |
| extern long sys_sysinfo(struct sysinfo *info); |
| extern long sys_stat64(char * filename, struct stat64 * statbuf, long flags); |
| extern long sys_lstat64(char * filename, struct stat64 * statbuf, long flags); |
| extern long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags); |
| extern long sys_times(struct tms * tbuf); |
| extern long sys_chroot(const char * filename); |
| extern long sys_creat(const char * pathname, int mode); |
| extern long sys_query_module(const char *name_user, int which, char *buf, |
| size_t bufsize, size_t *ret); |
| static int sys_fork(void) |
| { |
| return do_fork(SIGCHLD, 0, NULL); |
| } |
| |
| int sys_vfork(void) |
| { |
| return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL); |
| } |
| |
| struct mmap_arg_struct { |
| unsigned long addr; |
| unsigned long len; |
| unsigned long prot; |
| unsigned long flags; |
| unsigned long fd; |
| unsigned long offset; |
| }; |
| |
| static int old_mmap(struct mmap_arg_struct *arg) |
| { |
| int error = -EFAULT; |
| struct file * file = NULL; |
| struct mmap_arg_struct a; |
| |
| if (copy_from_user(&a, arg, sizeof(a))) |
| return -EFAULT; |
| |
| down(¤t->mm->mmap_sem); |
| lock_kernel(); |
| if (!(a.flags & MAP_ANONYMOUS)) { |
| error = -EBADF; |
| file = fget(a.fd); |
| if (!file) |
| goto out; |
| } |
| a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); |
| |
| error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); |
| if (file) |
| fput(file); |
| out: |
| unlock_kernel(); |
| up(¤t->mm->mmap_sem); |
| return error; |
| } |
| |
| /* |
| * sys_pipe() is the normal C calling standard for creating |
| * a pipe. It's not the way unix traditionally does this, though. |
| */ |
| static int sys_pipe(unsigned long * fildes) |
| { |
| int fd[2]; |
| int error; |
| |
| lock_kernel(); |
| error = do_pipe(fd); |
| unlock_kernel(); |
| if (!error) { |
| if (copy_to_user(fildes, fd, 2*sizeof(int))) |
| error = -EFAULT; |
| } |
| return error; |
| } |
| |
| static int sys_pause(void) |
| { |
| current->state = TASK_INTERRUPTIBLE; |
| schedule(); |
| return -ERESTARTNOHAND; |
| } |
| |
| static int sys_sigaction(int sig, const struct old_sigaction *act, |
| struct old_sigaction *oact) |
| { |
| struct k_sigaction new_ka, old_ka; |
| int ret; |
| |
| if (act) { |
| old_sigset_t mask; |
| if (verify_area(VERIFY_READ, act, sizeof(*act)) || |
| __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
| __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) |
| return -EFAULT; |
| __get_user(new_ka.sa.sa_flags, &act->sa_flags); |
| __get_user(mask, &act->sa_mask); |
| siginitset(&new_ka.sa.sa_mask, mask); |
| } |
| |
| ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
| |
| if (!ret && oact) { |
| if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || |
| __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
| __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) |
| return -EFAULT; |
| __put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
| __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); |
| } |
| |
| return ret; |
| } |
| |
| |
| /* |
| * sys_ipc() is the de-multiplexer for the SysV IPC calls.. |
| * |
| * This is really horribly ugly. |
| */ |
| int sys_ipc (uint call, int first, int second, |
| int third, void *ptr, long fifth) |
| { |
| int version, ret; |
| |
| version = call >> 16; /* hack for backward compatibility */ |
| call &= 0xffff; |
| |
| switch (call) { |
| case SEMOP: |
| return sys_semop (first, (struct sembuf *)ptr, second); |
| case SEMGET: |
| return sys_semget (first, second, third); |
| case SEMCTL: { |
| union semun fourth; |
| if (!ptr) |
| return -EINVAL; |
| if (get_user(fourth.__pad, (void **) ptr)) |
| return -EFAULT; |
| return sys_semctl (first, second, third, fourth); |
| } |
| |
| case MSGSND: |
| return sys_msgsnd (first, (struct msgbuf *) ptr, |
| second, third); |
| case MSGRCV: |
| switch (version) { |
| case 0: { |
| struct ipc_kludge tmp; |
| if (!ptr) |
| return -EINVAL; |
| |
| if (copy_from_user(&tmp, |
| (struct ipc_kludge *) ptr, |
| sizeof (tmp))) |
| return -EFAULT; |
| return sys_msgrcv (first, tmp.msgp, second, |
| tmp.msgtyp, third); |
| } |
| default: |
| panic("msgrcv with version != 0"); |
| return sys_msgrcv (first, |
| (struct msgbuf *) ptr, |
| second, fifth, third); |
| } |
| case MSGGET: |
| return sys_msgget ((key_t) first, second); |
| case MSGCTL: |
| return sys_msgctl (first, second, (struct msqid_ds *) ptr); |
| |
| case SHMAT: |
| switch (version) { |
| default: { |
| ulong raddr; |
| ret = sys_shmat (first, (char *) ptr, second, &raddr); |
| if (ret) |
| return ret; |
| return put_user (raddr, (ulong *) third); |
| } |
| case 1: /* iBCS2 emulator entry point */ |
| if (!segment_eq(get_fs(), get_ds())) |
| return -EINVAL; |
| return sys_shmat (first, (char *) ptr, second, (ulong *) third); |
| } |
| case SHMDT: |
| return sys_shmdt ((char *)ptr); |
| case SHMGET: |
| return sys_shmget (first, second, third); |
| case SHMCTL: |
| return sys_shmctl (first, second, |
| (struct shmid_ds *) ptr); |
| default: |
| return -EINVAL; |
| } |
| } |
| |
| int nsyscalls = 0; |
| |
| int execute_syscall(int syscall, unsigned long *args) |
| { |
| unsigned long arg1, arg2, arg3, arg4, arg5; |
| int res; |
| |
| current->thread.nsyscalls++; |
| nsyscalls++; |
| if(syscall == -1) |
| panic("syscall thread activated without a system call"); |
| arg1 = args[0]; |
| arg2 = args[1]; |
| arg3 = args[2]; |
| arg4 = args[3]; |
| arg5 = args[4]; |
| switch(syscall){ |
| case __NR_exit: /* 1 */ |
| res = sys_exit(arg1); |
| break; |
| case __NR_fork: /* 2 */ |
| current->thread.forking = 1; |
| res = sys_fork(); |
| current->thread.forking = 0; |
| break; |
| case __NR_read: /* 3 */ |
| res = sys_read(arg1, (char *) arg2, arg3); |
| break; |
| case __NR_write: /* 4 */ |
| res = sys_write(arg1, (char *) arg2, arg3); |
| break; |
| case __NR_open: /* 5 */ |
| res = sys_open((char *) arg1, arg2, arg3); |
| break; |
| case __NR_close: /* 6 */ |
| res = sys_close(arg1); |
| break; |
| case __NR_creat: /* 8 */ |
| res = sys_creat((const char *) arg1, arg2); |
| break; |
| case __NR_link: /* 9 */ |
| res = sys_link((const char *) arg1, (const char *) arg2); |
| break; |
| case __NR_unlink: /* 10 */ |
| res = sys_unlink((char *)arg1); |
| break; |
| case __NR_execve: /* 11 */ |
| res = sys_execve((char *) arg1, (char **) arg2, (char **) arg3); |
| printk("exec of \"%s\" returned %d\n", (char *) arg1, res); |
| break; |
| case __NR_chdir: /* 12 */ |
| res = sys_chdir((char *) arg1); |
| break; |
| case __NR_time: /* 13 */ |
| res = sys_time((int *) arg1); |
| break; |
| case __NR_mknod: |
| res = sys_mknod((const char *) arg1, arg2, arg3); |
| break; |
| case __NR_chmod: /* 15 */ |
| res = sys_chmod((const char *) arg1, arg2); |
| break; |
| case __NR_lchown: /* 16 */ |
| res = sys_lchown((const char *) arg1, arg2, arg3); |
| break; |
| case __NR_lseek: /* 19 */ |
| res = sys_lseek(arg1, arg2, arg3); |
| break; |
| case __NR_getpid: /* 20 */ |
| res = sys_getpid(); |
| break; |
| case __NR_mount: /* 21 */ |
| res = sys_mount((char *) arg1, (char *) arg2, (char *) arg3, arg4, |
| (void *) arg5); |
| break; |
| case __NR_umount: /* 22 */ |
| res = sys_oldumount((char *) arg1); |
| break; |
| case __NR_setuid: /* 23 */ |
| res = sys_setuid(arg1); |
| break; |
| case __NR_getuid: /* 24 */ |
| res = sys_getuid(); |
| break; |
| case __NR_alarm: /* 27 */ |
| res = sys_alarm(arg1); |
| break; |
| case __NR_pause: /* 29 */ |
| res = sys_pause(); |
| break; |
| case __NR_utime: /* 30 */ |
| res = sys_utime((char *) arg1, (struct utimbuf *) arg2); |
| break; |
| case __NR_access: /* 33 */ |
| res = sys_access((char *) arg1, arg2); |
| break; |
| case __NR_sync: /* 36 */ |
| res = sys_sync(); |
| break; |
| case __NR_kill: /* 37 */ |
| res = sys_kill(arg1, arg2); |
| break; |
| case __NR_rename: /* 38 */ |
| res = sys_rename((const char *) arg1, (const char *) arg2); |
| break; |
| case __NR_mkdir: /* 39 */ |
| res = sys_mkdir((const char *) arg1, arg2); |
| break; |
| case __NR_rmdir: /* 40 */ |
| res = sys_rmdir((const char *) arg1); |
| break; |
| case __NR_dup: /* 41 */ |
| res = sys_dup(arg1); |
| break; |
| case __NR_pipe: /* 42 */ |
| res = sys_pipe((unsigned long *) arg1); |
| break; |
| case __NR_times: /* 43 */ |
| res = sys_times((struct tms *) arg1); |
| break; |
| case __NR_brk: /* 45 */ |
| res = sys_brk(arg1); |
| break; |
| case __NR_setgid: /* 46 */ |
| res = sys_setgid(arg1); |
| break; |
| case __NR_getgid: /* 47 */ |
| res = sys_getgid(); |
| break; |
| case __NR_geteuid: /* 49 */ |
| res = sys_geteuid(); |
| break; |
| case __NR_getegid: /* 50 */ |
| res = sys_getegid(); |
| break; |
| case __NR_umount2: /* 52 */ |
| res = sys_umount((char *) arg1, arg2); |
| break; |
| case __NR_ioctl: /* 54 */ |
| res = sys_ioctl(arg1, arg2, arg3); |
| break; |
| case __NR_fcntl: /* 55 */ |
| res = sys_fcntl(arg1, arg2, arg3); |
| break; |
| case __NR_setpgid: /* 57 */ |
| res = sys_setpgid(arg1, arg2); |
| break; |
| case __NR_umask: /* 60 */ |
| res = sys_umask(arg1); |
| break; |
| case __NR_chroot: /* 61 */ |
| res = sys_chroot((const char *) arg1); |
| break; |
| case __NR_dup2: /* 63 */ |
| res = sys_dup2(arg1, arg2); |
| break; |
| case __NR_getppid: /* 64 */ |
| res = sys_getppid(); |
| break; |
| case __NR_getpgrp: /* 65 */ |
| res = sys_getpgrp(); |
| break; |
| case __NR_setsid: /* 66 */ |
| res = sys_setsid(); |
| break; |
| case __NR_sigaction: /* 67 */ |
| res = sys_sigaction(arg1, (struct old_sigaction *) arg2, |
| (struct old_sigaction *) arg3); |
| break; |
| case __NR_setreuid: /* 70 */ |
| res = sys_setreuid(arg1, arg2); |
| break; |
| case __NR_setregid: /* 71 */ |
| res = sys_setregid(arg1, arg2); |
| break; |
| case __NR_sethostname: /* 74 */ |
| res = sys_sethostname((char *) arg1, arg2); |
| break; |
| case __NR_getrlimit: /* 75 */ |
| res = sys_getrlimit(arg1, (struct rlimit *) arg2); |
| break; |
| case __NR_setrlimit: /* 76 */ |
| res = sys_setrlimit(arg1, (struct rlimit *) arg2); |
| break; |
| case __NR_getrusage: /* 77 */ |
| res = sys_getrusage(arg1, (struct rusage *) arg2); |
| break; |
| case __NR_gettimeofday: /* 78 */ |
| res = sys_gettimeofday((struct timeval *) arg1, (struct timezone *) arg2); |
| break; |
| case __NR_getgroups: /* 80 */ |
| res = sys_getgroups(arg1, (gid_t *) arg2); |
| break; |
| case __NR_setgroups: /* 81 */ |
| res = sys_setgroups(arg1, (gid_t *) arg2); |
| break; |
| case __NR_symlink: /* 83 */ |
| res = sys_symlink((const char *) arg1, (const char *) arg2); |
| break; |
| case __NR_readlink: /* 85 */ |
| res = sys_readlink((const char *) arg1, (char *) arg2, arg3); |
| break; |
| case __NR_swapon: /* 87 */ |
| res = sys_swapon((const char *) arg1, arg2); |
| break; |
| case __NR_reboot: /* 88 */ |
| res = sys_reboot(arg1, arg2, arg3); |
| break; |
| case __NR_mmap: /* 90 */ |
| res = old_mmap((struct mmap_arg_struct *) arg1); |
| break; |
| case __NR_munmap: /* 91 */ |
| res = sys_munmap(arg1, arg2); |
| break; |
| case __NR_ftruncate: /* 93 */ |
| res = sys_ftruncate(arg1, arg2); |
| break; |
| case __NR_fchmod: /* 94 */ |
| res = sys_fchmod(arg1, arg2); |
| break; |
| case __NR_fchown: |
| res = sys_fchown(arg1, arg2, arg3); |
| break; |
| case __NR_getpriority: /* 96 */ |
| res = sys_getpriority(arg1, arg2); |
| break; |
| case __NR_setpriority: /* 97 */ |
| res = sys_setpriority(arg1, arg2, arg3); |
| break; |
| case __NR_statfs: /* 99 */ |
| res = sys_statfs((const char *) arg1, (struct statfs *) arg2); |
| break; |
| case __NR_fstatfs: /* 100 */ |
| res = sys_fstatfs(arg1, (struct statfs *) arg2); |
| break; |
| case __NR_ioperm: /* 101 */ |
| /* User-mode has no io ports */ |
| res = 0; |
| break; |
| case __NR_socketcall: /* 102 */ |
| res = sys_socketcall(arg1, (unsigned long *) arg2); |
| break; |
| case __NR_syslog: /* 103 */ |
| res = sys_syslog(arg1, (char *) arg2, arg3); |
| break; |
| case __NR_stat: /* 106 */ |
| res = sys_newstat((char *) arg1, (struct stat *) arg2); |
| break; |
| case __NR_lstat: /* 107 */ |
| res = sys_newlstat((char *) arg1, (struct stat *) arg2); |
| break; |
| case __NR_fstat: /* 108 */ |
| res = sys_newfstat(arg1, (struct stat *) arg2); |
| break; |
| case __NR_iopl: /* 110 */ |
| /* Fake this one */ |
| res = 0; |
| break; |
| case __NR_vhangup: /* 111 */ |
| res = sys_vhangup(); |
| break; |
| case __NR_wait4: /* 114 */ |
| res = sys_wait4(arg1, (unsigned int *) arg2, arg3, (struct rusage *) arg4); |
| break; |
| case __NR_swapoff: /* 115 */ |
| res = sys_swapoff((char *) arg1); |
| break; |
| case __NR_sysinfo: /* 116 */ |
| res = sys_sysinfo((struct sysinfo *) arg1); |
| break; |
| case __NR_ipc: /* 117 */ |
| res = sys_ipc(arg1, arg2, arg3, arg4, (void *) arg5, 0); |
| break; |
| case __NR_fsync: /* 118 */ |
| res = sys_fsync(arg1); |
| break; |
| case __NR_setdomainname: /* 121 */ |
| res = sys_setdomainname((char *)arg1, arg2); |
| break; |
| case __NR_uname: /* 122 */ |
| res = sys_newuname((struct new_utsname *) arg1); |
| break; |
| case __NR_mprotect: /* 125 */ |
| res = sys_mprotect(arg1, arg2, arg3); |
| break; |
| case __NR_sigprocmask: /* 126 */ |
| res = sys_sigprocmask(arg1, (sigset_t *) arg2, (sigset_t *) arg3); |
| break; |
| case __NR_delete_module: /* 129 */ |
| res = sys_delete_module((const char *) arg1); |
| break; |
| case __NR_get_kernel_syms: /* 130 */ |
| res = sys_get_kernel_syms((struct kernel_sym *) arg1); |
| break; |
| case __NR_quotactl: /* 131 */ |
| res = sys_quotactl(arg1, (const char *) arg2, arg3, (caddr_t) arg4); |
| break; |
| case __NR_getpgid: /* 132 */ |
| res = sys_getpgid(arg1); |
| break; |
| case __NR_fchdir: /* 133 */ |
| res = sys_fchdir(arg1); |
| break; |
| case __NR_bdflush: /* 134 */ |
| res = sys_bdflush(arg1, arg2); |
| break; |
| case __NR_personality: /* 136 */ |
| res = sys_personality(arg1); |
| break; |
| case __NR_setfsuid: /* 138 */ |
| res = sys_setfsuid(arg1); |
| break; |
| case __NR_setfsgid: /* 139 */ |
| res = sys_setfsgid(arg1); |
| break; |
| case __NR__llseek: /* 140 */ |
| res = sys_llseek(arg1, arg2, arg3, (loff_t *) arg4, arg5); |
| break; |
| case __NR_getdents: /* 141 */ |
| res = sys_getdents(arg1, (void *) arg2, arg3); |
| break; |
| case __NR__newselect: /* 142 */ |
| res = sys_select(arg1, (fd_set *) arg2, (fd_set *) arg3, (fd_set *) arg4, |
| (struct timeval *) arg5); |
| break; |
| case __NR_flock: /* 143 */ |
| res = sys_flock(arg1, arg2); |
| break; |
| case __NR_msync: /* 144 */ |
| res = sys_msync(arg1, arg2, arg3); |
| break; |
| case __NR_writev: /* 146 */ |
| res = sys_writev(arg1, (const struct iovec *) arg2, arg3); |
| break; |
| case __NR_nanosleep: /* 162 */ |
| res = sys_nanosleep((struct timespec *) arg1, (struct timespec *) arg2); |
| break; |
| case __NR_mremap: /* 163 */ |
| res = sys_mremap(arg1, arg2, arg3, arg4, arg5); |
| break; |
| case __NR_setresuid: /* 164 */ |
| res = sys_setresuid(arg1, arg2, arg3); |
| break; |
| case __NR_query_module: |
| res = sys_query_module((const char *) arg1, arg2, (char *) arg3, |
| arg4, (size_t *) arg5); |
| break; |
| case __NR_poll: /* 168 */ |
| res = sys_poll((struct pollfd *) arg1, arg2, arg3); |
| break; |
| case __NR_rt_sigaction: /* 174 */ |
| res = sys_rt_sigaction(arg1, (const struct sigaction *) arg2, |
| (struct sigaction *) arg3, arg4); |
| break; |
| case __NR_rt_sigprocmask: /* 175 */ |
| res = sys_rt_sigprocmask(arg1, (sigset_t *) arg2, (sigset_t *) arg3, |
| arg4); |
| break; |
| case __NR_rt_sigsuspend: /* 179 */ |
| res = sys_rt_sigsuspend((sigset_t *) arg1, arg2); |
| break; |
| case __NR_chown: /* 182 */ |
| res = sys_chown((const char *) arg1, arg2, arg3); |
| break; |
| case __NR_getcwd: /* 183 */ |
| res = sys_getcwd((char *) arg1, arg2); |
| break; |
| case __NR_vfork: /* 190 */ |
| current->thread.forking = 1; |
| res = sys_vfork(); |
| current->thread.forking = 0; |
| break; |
| case __NR_stat64: /* 195 */ |
| res = sys_stat64((char *) arg1, (struct stat64 *) arg2, arg3); |
| break; |
| case __NR_lstat64: /* 196 */ |
| res = sys_lstat64((char *) arg1, (struct stat64 *) arg2, arg3); |
| break; |
| case __NR_fstat64: /* 197 */ |
| res = sys_fstat64(arg1, (struct stat64 *) arg2, arg3); |
| break; |
| default: |
| printk("Unimplemented syscall : %d\n", syscall); |
| res = -ENOSYS; |
| KERN_UNTESTED(); |
| break; |
| } |
| return(res); |
| } |
| |
| void store_syscall(void *t, int syscall, unsigned long arg1, |
| unsigned long arg2, unsigned long arg3, unsigned long arg4, |
| unsigned long arg5) |
| { |
| struct task_struct *task; |
| |
| task = t; |
| task->thread.syscall.id = syscall; |
| task->thread.syscall.args[0] = arg1; |
| task->thread.syscall.args[1] = arg2; |
| task->thread.syscall.args[2] = arg3; |
| task->thread.syscall.args[3] = arg4; |
| task->thread.syscall.args[4] = arg5; |
| } |
| |
| void set_syscall_result(void *t, int result, int again) |
| { |
| struct task_struct *task; |
| |
| if(t == NULL) task = current; |
| else task = t; |
| if(task->thread.syscall.have_result) |
| panic("Already have result in set_syscall_result"); |
| task->thread.syscall.result = result; |
| task->thread.syscall.again = again; |
| task->thread.syscall.have_result = 1; |
| } |
| |
| int have_syscall_result(void *t, long *result_out, int *again_out) |
| { |
| struct task_struct *task; |
| |
| task = t; |
| if(task->thread.syscall.have_result){ |
| task->thread.syscall.have_result = 0; |
| *result_out = task->thread.syscall.result; |
| *again_out = task->thread.syscall.again; |
| return(1); |
| } |
| else return(0); |
| } |
| |
| int current_syscall(void *t, unsigned long *args_out) |
| { |
| struct task_struct *task; |
| |
| if(t == NULL) task = current; |
| else task = t; |
| args_out[0] = task->thread.syscall.args[0]; |
| args_out[1] = task->thread.syscall.args[1]; |
| args_out[2] = task->thread.syscall.args[2]; |
| args_out[3] = task->thread.syscall.args[3]; |
| args_out[4] = task->thread.syscall.args[4]; |
| return(task->thread.syscall.id); |
| } |
| |
| int redoing_syscall(void *t, unsigned long *args_out, long *result_out) |
| { |
| struct task_struct *task; |
| |
| task = t; |
| if(task->thread.syscall.again == 0) return(-1); |
| *result_out = task->thread.syscall.result; |
| return(current_syscall(task, args_out)); |
| } |
| |
| spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED; |
| |
| void lock_syscall(void) |
| { |
| spin_lock(&syscall_lock); |
| } |
| |
| void unlock_syscall(void) |
| { |
| spin_unlock(&syscall_lock); |
| } |