syscalls.c
来自「底层驱动开发」· C语言 代码 · 共 185 行
C
185 行
/* * Copyright 2003 PathScale, Inc. * * Licensed under the GPL */#include "linux/linkage.h"#include "linux/slab.h"#include "linux/shm.h"#include "linux/utsname.h"#include "linux/personality.h"#include "asm/uaccess.h"#define __FRAME_OFFSETS#include "asm/ptrace.h"#include "asm/unistd.h"#include "asm/prctl.h" /* XXX This should get the constants from libc */#include "choose-mode.h"#include "kern.h"asmlinkage long sys_uname64(struct new_utsname __user * 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;}#ifdef CONFIG_MODE_TTextern int modify_ldt(int func, void *ptr, unsigned long bytecount);long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount){ /* XXX This should check VERIFY_WRITE depending on func, check this * in i386 as well. */ if (!access_ok(VERIFY_READ, ptr, bytecount)) return -EFAULT; return(modify_ldt(func, ptr, bytecount));}#endif#ifdef CONFIG_MODE_SKASextern int userspace_pid[];#include "skas_ptrace.h"long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount){ struct ptrace_ldt ldt; void *buf; int res, n; buf = kmalloc(bytecount, GFP_KERNEL); if(buf == NULL) return(-ENOMEM); res = 0; switch(func){ case 1: case 0x11: res = copy_from_user(buf, ptr, bytecount); break; } if(res != 0){ res = -EFAULT; goto out; } ldt = ((struct ptrace_ldt) { .func = func, .ptr = buf, .bytecount = bytecount });#warning Need to look up userspace_pid by cpu res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt); if(res < 0) goto out; switch(func){ case 0: case 2: n = res; res = copy_to_user(ptr, buf, n); if(res != 0) res = -EFAULT; else res = n; break; } out: kfree(buf); return(res);}#endiflong sys_modify_ldt(int func, void *ptr, unsigned long bytecount){ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func, ptr, bytecount));}#ifdef CONFIG_MODE_TTextern long arch_prctl(int code, unsigned long addr);static long arch_prctl_tt(int code, unsigned long addr){ unsigned long tmp; long ret; switch(code){ case ARCH_SET_GS: case ARCH_SET_FS: ret = arch_prctl(code, addr); break; case ARCH_GET_FS: case ARCH_GET_GS: ret = arch_prctl(code, (unsigned long) &tmp); if(!ret) ret = put_user(tmp, &addr); break; default: ret = -EINVAL; break; } return(ret);}#endif#ifdef CONFIG_MODE_SKAS/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */static long arch_prctl_skas(int code, unsigned long addr){ long ret = 0; switch(code){ case ARCH_SET_FS: current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr; break; case ARCH_SET_GS: current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr; break; case ARCH_GET_FS: ret = put_user(current->thread.regs.regs.skas. regs[FS_BASE / sizeof(unsigned long)], (unsigned long __user *)addr); break; case ARCH_GET_GS: ret = put_user(current->thread.regs.regs.skas. regs[GS_BASE / sizeof(unsigned long)], (unsigned long __user *)addr); break; default: ret = -EINVAL; break; } return(ret);}#endiflong sys_arch_prctl(int code, unsigned long addr){ return(CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code, addr));}long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid){ long ret; if (!newsp) newsp = UPT_SP(¤t->thread.regs.regs); current->thread.forking = 1; ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, child_tid); current->thread.forking = 0; return(ret);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?