X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fsyscalls.c;h=7b4855ce5e2c6d8b852c714235fe1e2adf54a11e;hb=6274aaa8894e14462a36c69090e2f9235f130e31;hp=0348d57ada02980199fe27f2a9df79bf9fc79da2;hpb=d0b4559f2936f6d9f06be0f7c3c51527a480ec0d;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/syscalls.c b/KernelLand/Kernel/syscalls.c index 0348d57a..7b4855ce 100644 --- a/KernelLand/Kernel/syscalls.c +++ b/KernelLand/Kernel/syscalls.c @@ -12,25 +12,37 @@ #include #include +#if 1 +# define MERR(f,v...) Log_Debug("Syscalls", "0x%x "f, callNum ,## v) +#else +# define MERR(v...) do{}while(0) +#endif + #define CHECK_NUM_NULLOK(v,size) \ - if((v)&&!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;} + if((v)&&!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NULLOK: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;} #define CHECK_STR_NULLOK(v) \ - if((v)&&!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;} + if((v)&&!Syscall_ValidString((v))){MERR("CHECK_STR_NULLOK: %p FAIL",v);ret=-1;err=-EINVAL;break;} #define CHECK_NUM_NONULL(v,size) \ - if(!(v)||!Syscall_Valid((size),(v))){ret=-1;err=-EINVAL;break;} + if(!(v)||!Syscall_Valid((size),(v))){MERR("CHECK_NUM_NONULL: %p(%x) FAIL",v,size);ret=-1;err=-EINVAL;break;} #define CHECK_STR_NONULL(v) \ - if(!(v)||!Syscall_ValidString((v))){ret=-1;err=-EINVAL;break;} + if(!(v)||!Syscall_ValidString((v))){MERR("CHECK_STR_NONULL: %p FAIL",v);ret=-1;err=-EINVAL;break;} #define CHECK_STR_ARRAY(arr) do {\ int i;\ char **tmp = (char**)arr; \ - CHECK_NUM_NONULL( tmp, sizeof(char**) ); \ - for(i=0;tmp[i];i++) { \ + CHECK_NUM_NULLOK( tmp, sizeof(char**) ); \ + for(i=0;tmp&&tmp[i];i++) { \ CHECK_STR_NONULL( tmp[i] ); \ CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \ }\ if(tmp[i]) break;\ } while(0) +#if BITS==64 +#define ARG64(idx1,idx2) ***ARG64 not used on 64-bit*** +#else +#define ARG64(idx1, idx2) (Regs->Arg##idx1|(((Uint64)Regs->Arg##idx2)<<32)) +#endif + // === IMPORTS === extern Uint Binary_Load(const char *file, Uint *entryPoint); @@ -38,6 +50,7 @@ extern Uint Binary_Load(const char *file, Uint *entryPoint); void SyscallHandler(tSyscallRegs *Regs); int Syscall_ValidString(const char *Addr); int Syscall_Valid(int Size, const void *Addr); + int Syscall_MM_SetFlags(void *Addr, Uint Flags, Uint Mask); // === CODE === // TODO: Do sanity checking on arguments, ATM the user can really fuck with the kernel @@ -65,6 +78,10 @@ void SyscallHandler(tSyscallRegs *Regs) // -- Put the current thread to sleep case SYS_SLEEP: Threads_Sleep(); break; + + case SYS_TIMEDSLEEP: + Time_Delay(Regs->Arg1); + break; // -- Yield current timeslice case SYS_YIELD: Threads_Yield(); break; @@ -106,14 +123,19 @@ void SyscallHandler(tSyscallRegs *Regs) break; // -- Map an address - case SYS_MAP: MM_Map(Regs->Arg1, Regs->Arg2); break; + case SYS_MAP: MM_Map((void*)Regs->Arg1, Regs->Arg2); break; // -- Allocate an address - case SYS_ALLOCATE: ret = MM_Allocate(Regs->Arg1); break; + case SYS_ALLOCATE: ret = MM_Allocate((void*)Regs->Arg1); break; // -- Unmap an address - case SYS_UNMAP: MM_Deallocate(Regs->Arg1); break; + case SYS_UNMAP: MM_Deallocate((void*)Regs->Arg1); break; + // -- Change the protection on an address + case SYS_SETFLAGS: + ret = Syscall_MM_SetFlags((void*)Regs->Arg1, Regs->Arg2, Regs->Arg3); + break; + // -- Get Thread/Process IDs case SYS_GETTID: ret = Threads_GetTID(); break; case SYS_GETPID: ret = Threads_GetPID(); break; @@ -135,13 +157,10 @@ void SyscallHandler(tSyscallRegs *Regs) // -- Check for messages case SYS_GETMSG: CHECK_NUM_NULLOK( (Uint*)Regs->Arg1, sizeof(Uint) ); - // NOTE: Can't do range checking as we don't know the size - // - Should be done by Proc_GetMessage - if( Regs->Arg2 && Regs->Arg2 != -1 && !MM_IsUser(Regs->Arg2) ) { - err = -EINVAL; ret = -1; break; - } + if( Regs->Arg3 != -1 ) + CHECK_NUM_NULLOK((void*)Regs->Arg3, Regs->Arg2); // *Source, *Data - ret = Proc_GetMessage((Uint*)Regs->Arg1, (void*)Regs->Arg2); + ret = Proc_GetMessage((Uint*)Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3); break; // -- Get the current timestamp @@ -163,7 +182,8 @@ void SyscallHandler(tSyscallRegs *Regs) CHECK_STR_NONULL((const char*)Regs->Arg1); CHECK_STR_ARRAY((const char**)Regs->Arg2); CHECK_STR_ARRAY((const char**)Regs->Arg3); - CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int)); + if( Regs->Arg4 > 0 ) + CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int)); ret = Proc_SysSpawn( (const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3, Regs->Arg4, (int*)Regs->Arg5 @@ -189,7 +209,20 @@ void SyscallHandler(tSyscallRegs *Regs) // Path, *Entrypoint ret = Binary_Load((char*)Regs->Arg1, (Uint*)Regs->Arg2); break; - + + // -- Load a kernel module + case SYS_LOADMOD: + CHECK_STR_NONULL( (const char *)Regs->Arg1 ); + if( Threads_GetUID() != 0 ) { + MERR("Not root"); + ret = EACCES; + } + else { + LOG("Module_LoadFile(\"%s\", NULL)", (const char *)Regs->Arg1); + ret = Module_LoadFile( (const char *)Regs->Arg1, NULL ); + } + break; + // --- // Virtual Filesystem // --- @@ -198,17 +231,32 @@ void SyscallHandler(tSyscallRegs *Regs) LOG("VFS_Open(\"%s\", 0x%x)", (char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER); ret = VFS_Open((char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER); break; + case SYS_REOPEN: + CHECK_STR_NONULL( (char*)Regs->Arg2 ); + LOG("VFS_Reopen(%i, \"%s\", 0x%x)", Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER); + ret = VFS_Reopen(Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3 | VFS_OPENFLAG_USER); + break; case SYS_CLOSE: LOG("VFS_Close(%i)", Regs->Arg1); VFS_Close( Regs->Arg1 ); break; + case SYS_COPYFD: + LOG("VFS_DuplicateFD(%i,%i)", Regs->Arg1, Regs->Arg2); + ret = VFS_DuplicateFD(Regs->Arg1, Regs->Arg2); + break; + + case SYS_FDCTL: + LOG("VFS_SetFDFlags(%i,0%o,0%o)", Regs->Arg1, Regs->Arg2, Regs->Arg3); + ret = VFS_SetFDFlags(Regs->Arg1, Regs->Arg2, Regs->Arg3); + break; + case SYS_SEEK: #if BITS == 64 ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 ); #else - ret = VFS_Seek( Regs->Arg1, Regs->Arg2|(((Uint64)Regs->Arg3)<<32), Regs->Arg4 ); + ret = VFS_Seek( Regs->Arg1, ARG64(2, 3), Regs->Arg4 ); #endif break; @@ -220,11 +268,41 @@ void SyscallHandler(tSyscallRegs *Regs) CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 ); ret = VFS_Write( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 ); break; + case SYS_WRITEAT: + #if BITS == 64 + CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg3 ); + ret = VFS_WriteAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 ); + #else + CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg4 ); + Debug("VFS_WriteAt(%i, %lli, %i, %p)", + Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5); + ret = VFS_WriteAt( Regs->Arg1, ARG64(2, 3), Regs->Arg4, (void*)Regs->Arg5 ); + #endif + break; case SYS_READ: CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 ); ret = VFS_Read( Regs->Arg1, Regs->Arg3, (void*)Regs->Arg2 ); break; + case SYS_READAT: + CHECK_NUM_NONULL( (void*)Regs->Arg5, Regs->Arg2 ); + #if BITS == 64 + ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, Regs->Arg3, (void*)Regs->Arg4 ); + #else + ret = VFS_ReadAt( Regs->Arg1, Regs->Arg2, ARG64(3, 4), (void*)Regs->Arg5 ); + #endif + break; + + case SYS_TRUNCATE: + ret = VFS_Truncate( + Regs->Arg1, + #if BITS == 32 + ARG64(2,3) + #else + Regs->Arg2 + #endif + ); + break; case SYS_FINFO: CHECK_NUM_NONULL( (void*)Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) ); @@ -262,6 +340,7 @@ void SyscallHandler(tSyscallRegs *Regs) case SYS_IOCTL: // All sanity checking should be done by the driver if( Regs->Arg3 && !MM_IsUser(Regs->Arg3) ) { + MERR("IOCtl Invalid arg %p", Regs->Arg3); err = -EINVAL; ret = -1; break; } ret = VFS_IOCtl( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 ); @@ -289,14 +368,10 @@ void SyscallHandler(tSyscallRegs *Regs) else { // Sanity check the paths - if(!Syscall_ValidString((char*)Regs->Arg1) - || !Syscall_ValidString((char*)Regs->Arg2) - || (Regs->Arg3 && !Syscall_ValidString((char*)Regs->Arg3)) - || !Syscall_ValidString((char*)Regs->Arg4) ) { - err = -EINVAL; - ret = -1; - break; - } + CHECK_STR_NONULL((char*)Regs->Arg1); + CHECK_STR_NONULL((char*)Regs->Arg2); + CHECK_STR_NULLOK((char*)Regs->Arg3); + CHECK_STR_NONULL((char*)Regs->Arg4); ret = VFS_Mount( (char*)Regs->Arg1, // Device (char*)Regs->Arg2, // Mount point @@ -329,16 +404,62 @@ void SyscallHandler(tSyscallRegs *Regs) 0 // User handles ); break; + + case SYS_MMAP: + ret = (tVAddr)VFS_MMap( + (void*)Regs->Arg1, Regs->Arg2, + Regs->Arg3&0xFFFF, Regs->Arg3>>16, + Regs->Arg4, + #if BITS == 32 + ARG64(5,6) + #else + Regs->Arg5 + #endif + ); + break; + case SYS_MUNMAP: + ret = VFS_MUnmap( (void*)Regs->Arg1, Regs->Arg2 ); + break; + + // Create a directory + case SYS_MKDIR: + CHECK_STR_NONULL( (char*)Regs->Arg1 ); + ret = VFS_MkDir( (char*)Regs->Arg1 ); + break; + + case SYS_UNLINK: + Log_Error("Syscalls", "TODO: Impliment SYS_UNLINK"); + break; + case SYS_MARSHALFD: + ret = VFS_MarshalHandle(Regs->Arg1); + break; + case SYS_UNMARSHALFD: + #if BITS == 64 + ret = VFS_UnmarshalHandle( Regs->Arg1 ); + #else + ret = VFS_UnmarshalHandle( ARG64(1,2) ); + #endif + break; + // -- Debug //#if DEBUG_BUILD - case SYS_DEBUG: + case SYS_DEBUGS: + CHECK_STR_NONULL( (char*)Regs->Arg1 ); + Log("Log: %08lli [%i] %s", now(), Threads_GetTID(), (const char*)Regs->Arg1); + break; + case SYS_DEBUGF: CHECK_STR_NONULL( (char*)Regs->Arg1 ); LogF("Log: %08lli [%i] ", now(), Threads_GetTID()); LogF((const char*)Regs->Arg1, Regs->Arg2, Regs->Arg3, Regs->Arg4, Regs->Arg5, Regs->Arg6); LogF("\r\n"); break; + case SYS_DEBUGHEX: + CHECK_STR_NONULL( (char*)Regs->Arg1 ); + CHECK_NUM_NONULL( (void*)Regs->Arg2, Regs->Arg3 ); + Debug_HexDump( (const char*)Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 ); + break; //#endif // -- Default (Return Error) @@ -397,7 +518,31 @@ int Syscall_ValidString(const char *Addr) */ int Syscall_Valid(int Size, const void *Addr) { - if(!MM_IsUser( (tVAddr)Addr )) return 0; + if(!MM_IsUser( (tVAddr)Addr )) { + Log_Debug("Syscalls", "Syscall_Valid - %p not user", Addr); + return 0; + } return CheckMem( Addr, Size ); } + +int Syscall_MM_SetFlags(void *Addr, Uint Flags, Uint Mask) +{ + tPAddr paddr = MM_GetPhysAddr(Addr); + Flags &= MM_PFLAG_RO|MM_PFLAG_EXEC; + Mask &= MM_PFLAG_RO|MM_PFLAG_EXEC; + + //Log_Debug("Syscalls", "SYS_SETFLAGS: %p %x %x", Addr, Flags, Mask); + + // Enable write? + if( (Mask & MM_PFLAG_RO) && !(Flags & MM_PFLAG_RO) ) { + void *node; + // HACK - Assume that RO mmap'd files are immutable + if( MM_GetPageNode(paddr, &node) == 0 && node ) { + Flags |= MM_PFLAG_COW; + Mask |= MM_PFLAG_COW; + } + } + MM_SetFlags(Addr, Flags, Mask); + return 0; +}